В этой статье представлен процесс настройки параметров, связанных с сборщиком мусора JVM, в производственной среде и предотвращено влияние зависаний сборщика мусора на уровень успешности служб JAVA путем настройки параметров.
В этот промежуток времени я разбирал статьи в серии jvm и случайно нашел эту статью.У автора есть четкая идея и окончательно решает проблему путем пошагового анализа. Лично мне нравится такой реальный боевой контент, и я делюсь статьей здесь с разрешения автора.Часть примечаний добавлена мной, в основном с целью пояснения.
Первоисточник: https://segmentfault.com/a/1190000005174819
Предыстория и возникшие проблемы
Наша HTTP-служба Java относится к типу OLTP и предъявляет относительно высокие требования к проценту успешных результатов и времени отклика.В производственной среде случайный показатель успешных результатов внезапно падает, а затем автоматически восстанавливается, как показано на рисунке:
Параметры, относящиеся к JVM и GC, следующие:
-Xmx22528m
-Xms22528m
-XX:NewRatio=2
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
скопировать код
Подводя итог, из-за интенсивного использования кэша в сервисе размер кучи открыт до 22G. Алгоритм GC использует CMS (UseConcMarkSweepGC), включает сокращение паузы меток (CMSParallelRemarkEnabled), устанавливает для молодого поколения параллельный сбор (UseParNewGC), а соотношение молодого поколения к старому составляет 1:2 (NewRatio=2). .
Параметры, относящиеся к журналу JVM GC, следующие:
-Xloggc:/data/gc.log
-XX:GCLogFileSize=10M
-XX:NumberOfGCLogFiles=10
-XX:+UseGCLogFileRotation
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+DisableExplicitGC
-verbose:gc
скопировать код
процесс решения проблем
Устранение проблем с использованием памяти приложения
Сначала используйте jmap для просмотра использования памяти:
jmap -histo:live PID
скопировать код
Эта команда сортирует текущие объекты в программе по количеству и занимаемому месту, а затем распечатывает их. Объектов, использующих исключения, здесь не обнаружено.
Устранение проблемы слишком большого количества содержимого кэша
Если содержимого кэша слишком много, возраст JVM будет легко заполнен, что приведет к частому сбору мусора, поэтому для просмотра вызывается журнал сборщика мусора.Обнаружено, что использование памяти обычно уменьшается с 20 ГБ до примерно 5G после каждого GC.Поэтому резидентный кэш памяти не является основной причиной долгосрочных зависаний GC. Есть много способов просмотреть GC LOG, использование VisualVM более интуитивно понятно, вам нужно использовать VisualGC:
На рисунке видно распределение пространства между Eden и старым возрастом.Поскольку общий объем памяти составляет 20 ГБ, установите -XX:NewRatio=2, чтобы старый возраст составлял 14 ГБ, Eden+S0+S1=7G.
Отрегулируйте момент времени GC (усугубляется проблема джиттера скорости успеха)
Если объем памяти, который требуется для обработки GC, относительно велик, время выполнения будет относительно большим, а время STW (Stop the World) будет больше. Согласно этой идее, скорректируйте момент запуска CMS, надеясь сделать GC раньше, то есть сделать GC чаще, но ожидать меньше времени на каждое выполнение. Добавлены следующие два параметра:
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=50
скопировать код
Это означает, что GC срабатывает, когда старая область используется на 50%. После эксперимента установлено, что частота ГК увеличилась, но снижение мощности Чэнь, вызванное каждым ГК, не ослабло, поэтому эти два параметра отбрасываются.
Отрегулируйте количество времени, в течение которого объект находится в памяти молодого поколения (эффект не очевиден)
Если вы можете уменьшить частоту GC в старом поколении, вы также можете уменьшить влияние GC.Поэтому старайтесь, чтобы объекты находились в памяти молодого поколения дольше, чтобы увеличить вероятность уничтожения этих объектов во время ГК молодого поколения. Использовать параметры-XX:MaxTenuringThreshold=31
После настройки эффект не очевиден.
Примечания: 1. MaxTenuringThreshold есть в версии 1.5.0.Максимальное значение может быть установлено на 31 до 05, 1.5.0После 06 максимальное значение может быть установлено на 15, а больше 15 будет считаться бесконечным. 2. Увеличить вероятность уничтожения ГК молодого поколения, но корректировка этого параметра малоэффективна, и значение возраста будет пересчитано во второй раз.
Принудительный сборщик мусора молодого поколения перед CMS-Remark
Прежде всего, добавьте соответствующие знания о CMS.Во всем процессе CMS есть два шага, которые являются STW, как показано в красной части:
CMS не имеет пауз, но заменяет длинные паузы алгоритма сортировки серийных меток двумя короткими паузами, цикл его сбора выглядит следующим образом:
-
1. Начальная метка (CMS-initial-mark), начиная с корневого объекта для маркировки уцелевших объектов
-
2. Параллельная отметка (CMS-concurrent-mark)
-
3. Замечание (CMS-замечание), приостановка всех потоков приложения и отмечание объектов, пропущенных на этапе параллельной маркировки (вызванное обновлением состояния объекта после фазы параллельной маркировки).
-
4. Параллельная очистка (CMS-concurrent-sweep)
-
5. Состояние параллельного сброса ожидает следующего триггера CMS (CMS-concurrent-reset).
Путем сравнения журнала GC с моментом времени, когда процент успешных попыток снизился, было обнаружено, что не каждый GC в старом поколении будет приводить к снижению процента успешных результатов, но была обнаружена закономерность:
Первые два процесса GC CMS-Remark вызвали падение показателя успеха примерно на 4 с, но третий GC не оказал существенного влияния на показатель успеха, а процесс CMS-Remark составил всего 0,18 с. Служба Java HTTP обратно проксируется через Nginx.Время ожидания, установленное nginx, составляет 3 с, поэтому, если GC зависнет в течение 3 с, это не окажет большого влияния на вероятность успеха.
Еще одно сообщение было найдено в журнале GC:
Смысла синей части в документации и сопутствующих материалах не нашел.Догадка - это объем памяти, обрабатываемой репликой.Чем больше обработка, тем медленнее будет. Добавьте следующие два параметра, чтобы принудительно запустить сборщик мусора молодого поколения перед этапом замечаний и этапом ПОЛНЫЙ сборщик мусора, чтобы уменьшить объем памяти, который необходимо обработать.
XX:+ScavengeBeforeFullGC
-XX:+CMSScavengeBeforeRemark
скопировать код
Примечание:
1. Значение синей части: примечание отмечает мощность объекта, который необходимо очистить.
2. Смысл выполнения GC молодого поколения перед стадией FULL GC заключается в том, что объекты в области Yong ссылаются на объекты в области Old.Если область Yong не очищается до очистки области Old, область Old будет на который ссылается область Йонга. Объект не может быть освобожден.
После настройки эффект очевиден.Ниже представлена диаграмма мониторинга успешности и времени отклика двух серверов с одинаковой конфигурацией в один и тот же период времени.Первый не добавляет параметр форсирования GC молодого поколения.
В заключение
1. На этапе CMS-remark необходимо обработать все объекты памяти в куче.Если перед этим этапом принудительно выполнить GC молодого поколения, то объем памяти, который необходимо обработать примечанием, будет сильно уменьшен, тем самым уменьшая влияние заморозки JVM на вероятность успеха. 2. Для HTTP-сервисов Java время приостановки JVM должно быть меньше, чем время ожидания вызова HTTP-клиента, в противном случае приостановка JVM повлияет на процент успешных вызовов.
Для выдающихся талантов нет недостатка в возможностях трудоустройства, для них есть только хорошие возможности. Но у них часто нет энергии, чтобы найти наилучший вариант среди множества возможностей.100offerТаланты и предприятия на платформе будут строго проверяться, чтобы могли встретиться «лучшие таланты» и «лучшие компании». Отсканируйте приведенный ниже QR-код, подпишитесь на 100offer и расскажите о своих ожиданиях от следующей работы. В течение недели получите 5-10 отличных возможностей для удовлетворения ваших требований!