В McAfee мы широко используем Apache Kafka. У нас есть 5+ кластеров с разным количеством брокеров.

29 июля мы получили Grafana Alert в одной из сред, в котором говорилось, что существуют разделы с несинхронизированными репликами. Это один из наиболее важных показателей при мониторинге kafka, и мы предполагаем, что это 100% точное описание производственного инцидента: Хьюстон, у нас есть проблема:

Другой график Grafana показал наиболее вероятную причину: один из брокеров перезапустился, что привело к рассинхронизации. Эта проблема длилась всего пару минут, после чего все вернулось в нормальное состояние.

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

В последующие дни то же самое появлялось снова и снова, обратите внимание на всплески в метрике Сборка мусора:

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

Поскольку эта проблема возникала почти ежедневно, мы обсудили и придумали стратегию:

В краткосрочной перспективе увеличьте объем памяти Heap на этом брокере, чтобы у нас было больше времени на передышку для проведения исследований. Параллельно мы должны подтвердить, что это была утечка памяти (или какая-то другая проблема), и посмотреть, что мы можем сделать, чтобы смягчить ее или окончательно исправить.

Сначала мы выделили 20 ГБ памяти кучи, чтобы обеспечить возможность роста. На приведенной выше диаграмме четко (синим цветом) показано, что объем памяти кучи превышает 6 ГБ и никогда не опускается до значения непосредственно выше. Это ясно показало, что память не высвобождается.

Тем временем мы занимались расширением памяти, мы начали упражнение по профилированию памяти. Это означает выполнение команды jmap (https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr014.html) в контейнере, в котором запущен Kafka:

jmap -dump:format=b,file=heap_dump.hprof <PID>

Это сделает снимок распределения памяти между разными классами. Затем вам нужно использовать такой инструмент, как Eclipse MAT или Visual VM, чтобы проанализировать этот дамп.

В этом случае это показывает, что класс org.apache.kafka.common.network.Selector занимает 95% пространства кучи. Явно утечка памяти в версии Kafka, которую мы использовали (0.10.2.1).

Отслеживая список коммитов в этом классе, выясняется, что исправление уже было для версии 2.2.1. Примечания к фиксации четко описывают проблему.

Итак, следующим шагом будет обновление версии брокера до версии 2.2.1 (по крайней мере), которая включает исправление. Но это было то, что потребовало бы нескольких недель для выполнения, поскольку в будущем были и другие зависимости.

Чтобы смягчить последствия перед обновлением, мы проанализировали, есть ли способ смягчить инициирующее действие, вызвавшее эту утечку. Было явно странное поведение: только один брокер в 6-узловом кластере демонстрировал такое поведение, другие - нет. В чем может быть причина такого поведения, наблюдаемого только у одного брокера?

Чтобы ответить на этот вопрос, мы потратили пару часов на игру с Kibana, фильтруя гигабайты журналов, чтобы обнаружить любой шаблон поведения, который покажет несбалансированное количество транзакций в этом брокере по сравнению с другими 5 в кластере. После небольшого исследования мы обнаружили, что количество записей в журнале для класса «GroupCoordinator» подозрительно различается у разных брокеров:

Основываясь на этом зацепке, мы обнаружили, что существует группа потребителей с определенным именем, у которой было много активности: каждую минуту потребитель присоединялся к этой группе потребителей (вызывая ребалансировку потребителей) и немедленно умирал, что заставляло кафка удалять его. от группы потребителей. Это происходило постоянно, и, что наиболее важно, активность этого потребителя затрагивала этого брокера больше, чем других, либо из-за разделов consumer_offsets, с которыми была связана эта группа потребителей, в этом брокере.

С этой информацией мы обратились к команде, которой принадлежала эта группа потребителей, чтобы они могли решить проблему, поскольку такое поведение не должно быть нормальным. Команда сообщила нам, что продукт в данный момент не активен, и мы можем остановить его, если захотим. После этого увеличение памяти кучи прекратилось (хотя уже просочившаяся память осталась там и не могла быть собрана).

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

Вот и все. После исследования мы можем подтвердить, что среднесрочное смягчение последствий было правильным, и мы предполагаем, что окончательное обновление до версии 2.3 определенно устранит проблему.

Команда: Фернандо, Родриго, Хьюго и я.