Расхождение между трассировкой Cassandra и задержкой на стороне клиента

Мы работаем на Cassandra 2.0.15 и наблюдаем огромные задержки чтения (> 60 секунд) с регулярными интервалами (примерно каждые 3 минуты) со всех хостов приложения. Мы измеряем эту задержку вокруг вызовов session.execute(stmt). В то же время, следы Кассандры сообщают о продолжительности <1 с. Мы также запустили в цикле запрос через cqlsh с тех же хостов в те пиковые времена задержки, и cqlsh всегда возвращался в течение 1 с. Чем можно объяснить это несоответствие на уровне драйвера Java?

- изменить: в ответ на комментарии -

Настройки JVM серверов Cassandra: -XX:+CMSClassUnloadingEnabled -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -XX:+HeapDumpOnOutOfMemoryError -Xss256k -XX:StringTableSize=1000003 -Xms32G -Xmx32G -XX:+UseG1GC -Djava.net.preferIPv4Stack=true -Dcassandra.jmx.local.port=7199 -XX:+DisableExplicitGC.

GC на стороне клиента ничтожно мал (ниже). Настройки клиента: -Xss256k -Xms4G -Xmx4G, версия драйвера Cassandra - 2.1.7.1

 GC на стороне клиента ничтожен

Код измерения на стороне клиента:

val selectServiceNames = session.prepare(QueryBuilder.select("service_name").from("service_names"))

override def run(): Unit = {
  val start = System.currentTimeMillis()
  try {
    val resultSet = session.execute(selectServiceNames.bind())
    val serviceNames = resultSet.all()
    val elapsed = System.currentTimeMillis() - start
    latency.add(elapsed) // emits metric to statsd
    if (elapsed > 10000) {
      log.info("Canary2 sensed high Cassandra latency: " + elapsed + "ms")
    }
  } catch {
    case e: Throwable =>
      log.error(e, "Canary2 select failed")
  } finally {
    Thread.sleep(100)
    schedule()
  }
}

Код создания кластера:

def createClusterBuilder(): Cluster.Builder = {
  val builder = Cluster.builder()
  val contactPoints = parseContactPoints()
  val defaultPort = findConnectPort(contactPoints)
  builder.addContactPointsWithPorts(contactPoints)
  builder.withPort(defaultPort) // This ends up config.protocolOptions.port
  if (cassandraUsername.isDefined && cassandraPassword.isDefined)
    builder.withCredentials(cassandraUsername(), cassandraPassword())
  builder.withRetryPolicy(ZipkinRetryPolicy.INSTANCE)
  builder.withLoadBalancingPolicy(new TokenAwarePolicy(new LatencyAwarePolicy.Builder(new RoundRobinPolicy()).build()))
}

Еще одно наблюдение, которое я не могу объяснить. Я запустил два потока, которые в цикле выполняют один и тот же запрос (как указано выше), единственная разница в том, что желтый поток спит 100 миллисекунд между запросами, а зеленый поток спит 60 секунд между запросами. Зеленая нить достигает низкой задержки (менее 1 с) гораздо чаще, чем желтая.

 введите описание изображения здесь

4 голоса | спросил Yuri Shkuro 18 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 18 Sep 2015 19:22:45 +0300 2015, 19:22:45

2 ответа


0

Я отследил проблему до времени ожидания запросов на узлах из удаленного центра обработки данных. Кластер имеет узлы в двух DC, но пространство ключей реплицируется только в локальном DC, поэтому удивительно, что удаление узлов даже рассматривалось. Я смог снизить задержку на

  1. изменение от ОДНОЙ до согласованности LOCAL_ONE и
  2. переход от простого циклического балансировщика нагрузки к постоянному току (также с учетом задержек и токенов).

Мне все еще кажется, что ошибка в драйвере Java заключается в том, что он пытается использовать узлы из удаленного центра обработки данных в качестве координационных узлов, когда пространство ключей явно не существует в этом центре обработки данных. Кроме того, даже если это было невозможно, я также использовал политику, учитывающую задержку, которая должна была исключить из рассмотрения удаленные узлы DC.

ответил Yuri Shkuro 29 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 29 Sep 2015 08:43:45 +0300 2015, 08:43:45
0

Это распространенная проблема, когда вы заставляете компонент самому себя тестировать.

  • возможны задержки, которые не видны рассматриваемым инструментам.
  • ваш компонент не знает, когда должен был начаться запрос.
  • когда JVM останавливается, это может помешать вам увидеть задержки, которые вы пытаетесь измерить.

Наиболее вероятное объяснение - второе. Допустим, у вас есть очередь из 100 задач, но поскольку система работает медленно, каждая задача занимает 1 секунду. Вы выполняете каждую задачу изнутри, и она видит, что это заняло 1 секунду, однако добавьте 100 задач в очередь, и первая из них запускается через 0 секунд, но последняя запускается через 99 секунд, а затем сообщает, что она заняла 1 секунду, но с вашей точки зрения для завершения потребовалось 100 секунд, из которых 99 секунд ожидали начала.

Могут также быть задержки в достижении вами результата, но это менее вероятно, если только операции, которые вы выполняете при обработке результатов, больше, чем требует база данных. то есть вы можете предположить, что узкое место находится на сервере.

ответил Peter Lawrey 18 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 18 Sep 2015 22:35:05 +0300 2015, 22:35:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132