Вопрос или проблема
Я сталкиваюсь с периодической неотзывчивостью Tomcat в нашей производственной среде. Я не могу воспроизвести это в тестовой среде, и в журналах ничего не появляется до или во время события. Tomcat продолжает работать, но перестает обрабатывать запросы. Я прочитал эту тему и добавил параметры вывода сбора мусора в JAVA_OPTS, хотя я еще не перезапускал Tomcat, чтобы они вступили в силу. Моя ситуация отличается тем, что tomcat/jvm, по-видимому, не восстанавливается или не “пробуждается”. Я подтвердил, что наше приложение было неотзывчивым как минимум на 15 минут несколько раз. Решение всегда заключается в перезапуске Tomcat (с использованием daemontools). Частота варьируется: иногда в часы пик, а иногда и посреди ночи (очень низкая нагрузка).
Я выделил до 4 ГБ памяти для JVM (-Xms2g -Xmx4g). На сервере 16 ГБ памяти, и работает он на 64-битной JVM. Белая книга Sun о настройке Java утверждает: “Выделение слишком большого объема физической памяти системы, возможно, приведет к пагинации виртуальной памяти на диск, вполне вероятно во время операций сбора мусора, что приведет к значительным проблемам с производительностью.” Установил ли я слишком большой размер кучи? Получу ли я выгоду от установки минимального размера равным максимальному?
Я не верю, что система перебрасывает память на диск. Вывод free -m показывает отсутствие использования свопа, и я установил swappiness на 0 в системе.
Когда неотзывчивость возникла сегодня в 2:30 утра, я быстро провел jstat и ps перед перезапуском Tomcat:
jstat показал аналогичные значения тому, что сейчас, с некоторыми исключениями: YGC было 431 против 44 сейчас, YGCT 10/1, FGC 59/7, FGCT 39/2, GCT 49/3
Вывод ps показал 1422832 резидентной и 5723580 виртуальной памяти. Это в сравнении с 1390036 и 5642668 вчера при нормальной работе.
Я не эксперт в этом, поэтому любая помощь будет оценена.
ОБНОВЛЕНИЕ: Хорошо, я добавил следующее в JAVA_OPTS и вскоре перезапущу Tomcat:
-XX:+UseConcMarkSweepGC -Xms2g -Xmx2g -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
Изменения следующие: 1) сменить алгоритм GC. 2) уменьшить максимальный размер кучи, так как, похоже, мне не нужно 4 ГБ, и очевидно, что избыточное выделение может вызвать периодический массовый сбор мусора. 3) Включить подробное ведение журнала GC. Спасибо всем.
Для начала полезная ссылка на “Настройка сбора мусора с помощью виртуальной машины Java TM версии 5.0”
Это действительно похоже на задержки GC, делающие Tomcat неотзывчивым. Одной из стратегий может быть использование сборщика мусора с “низкой задержкой” с опцией -XX:+UseConcMarkSweepGC
.
Мы несколько раз сталкивались с этим в нашей производственной среде, и причиной оказалось то, что сборка мусора java останавливала дальнейшие запросы. Самым явным показателем для нас было 100% использование процессора на как минимум одном из ядер в течение периода неотзывчивости.
Ответ в нашем случае заключался в том, чтобы отследить утечку памяти в приложении. Я не уверен, что это будет ответом для вас, но, по крайней мере, это еще одна точка данных.
Проблема все еще актуальна, я подал ее на bugzilla tomcat здесь
Однако ZGC работает хорошо –
export CATALINA_OPTS="-Xms10g -Xmx10g -XX:+UseZGC -XX:+ZGenerational"
Ответ или решение
Томкат периодически становится неотзывчивым в производственной среде: как решить проблему
Теория:
Периодическая неотзывчивость Tomcat в производственной среде может быть вызвана множеством факторов, однако одной из наиболее распространенных причин является неправильная работа сборщика мусора (Garbage Collector – GC) в JVM (Java Virtual Machine). Ваша текущая конфигурация выделяет до 4 ГБ памяти для JVM с использованием 64-битной версии, при этом всего на сервере 16 ГБ оперативной памяти. Хотя вы не видите обмена памяти на диск, стоит учитывать, что даже в этом случае могут возникать проблемы с памятью, которые влияют на производительность.
Garbage Collection (GC) используется для автоматического управления памятью, но в случае, если система сталкивается с большими объемами данных или проблемами с памятью, GC может занимать значительные ресурсы CPU, вызывая замедление или полную неотзывчивость сервера приложений. Также не исключено наличие утечек памяти в приложении, что постепенно увеличивает нагрузку на GC.
Пример:
Ваши наблюдения за работой GC через команду jstat подтверждают значительное количество операций младшего (YGC) и полного (FGC) GC, что может свидетельствовать о недостаточной оптимизации параметров GC. Активное использование процессорного времени и чрезвычайно больший объем виртуальной памяти также могут указывать на проблемы с оптимизацией JVM или утечками памяти в приложении.
Применение:
Для решения данной проблемы можно предпринять следующие шаги:
-
Спецификация GC: Включите использование "низкопаузабельного" сборщика мусора с помощью переключателя
-XX:+UseConcMarkSweepGC
или попробуйте использовать ZGC, который оптимизирован для работы с большими объемами данных и многопоточности, с опцией-XX:+UseZGC
. ZGC известен своей способностью минимизировать паузы и может стать отличным выбором для производственных сред. -
Тонкая настройка параметров GC: Параметры
-Xms2g
и-Xmx2g
означают, что выделяемая память будет одинакова на старте и в процессе работы, что может уменьшить необходимость частых операций GC. Однако, вам стоит внимательно следить за поведением приложения после внесения изменений. -
Включение расширенного логирования для GC: Используйте опции
-verbose:gc
,-XX:+PrintGCTimeStamps
, и-XX:+PrintGCDetails
для детального анализа и мониторинга работы GC. Это позволит вам выявить точное время и причины вызовов GC, что может оказаться полезным для дальнейшей оптимизации. -
Отслеживание утечек памяти: Запустите анализатор памяти (например, jVisualVM или другие инструменты профилирования), чтобы обнаружить потенциальные утечки памяти в вашем приложении. Утечки могут стать причиной неэффективного использования ресурсов и частых вызовов GC.
-
Мониторинг серверных ресурсов: Убедитесь, что вам доступны инструменты наблюдения за использованием CPU, памяти и другими системными ресурсами, чтобы своевременно выявлять превышение допустимых параметров нагрузки.
-
Обновление конфигурации: Учтите рекомендации по производительности, предоставленные в официальных документах Oracle для JVM, такие как указано здесь.
-
Обновление приложений и серверов: Периодически проверяйте наличие обновлений для Tomcat и библиотек, которые могут содержать критические исправления или улучшения производительности.
Следует помнить, что диагностика и решение таких проблем требуют системного подхода и могут потребовать переконфигурации различных элементов системы. Вы можете столкнуться с необходимостью адаптировать свои издначальные настройки в зависимости от уникальных особенностей и нагрузок вашего производственного окружения.