1. Принципы настройки
Настройка JVM может показаться сложной задачей, но помните, что настройка JVM должна быть последней пулей в оптимизации производительности Java.
Я согласен с точкой зрения г-на Ляо Сюэфэна. Необходимо понимать, что настройка JVM не является традиционным методом. Как правило, первый выбор при проблемах с производительностью — это оптимизация программы, а последний выбор — выполнить настройку JVM.
Автоматическое управление памятью JVM предназначено для того, чтобы вытащить разработчиков из трясины управления памятью. Даже если вам нужно настроить JVM, вы не должны настраивать параметры, просто хлопая себя по лбу, вы должны полностью контролировать и детально анализировать данные о производительности.
2. Сроки настройки JVM
В каких ситуациях необходимо учитывать настройку JVM?
- Память кучи (старого поколения) продолжает увеличиваться до установленного максимального значения памяти;
- Полная сборка мусора бывает часто;
- Время паузы GC слишком велико (более 1 секунды);
- Исключения памяти, такие как OutOfMemory, возникают в приложении;
- Есть приложения, использующие локальный кеш и занимающие много места в памяти;
- Пропускная способность и скорость отклика системы низкие или ухудшились.
3. Цель настройки JVM
Пропускная способность, задержка и использование памяти аналогичны CAP, образуя невозможный треугольник, для настройки можно выбрать только два из них, но не все три.
- Задержка: низкие паузы GC и низкая частота GC;
- низкое использование памяти;
- высокая пропускная способность;
Выбор двух из них неизбежно произойдет за счет другого.
Ниже приведены некоторые справочные примеры количественных целей для настройки JVM:
- Использование памяти кучи
- Использование памяти старого поколения
- средняя пауза
- Полный сбор мусора умножается на 0 или средний интервал паузы >= 24 часа;
Примечание. Цели количественной оценки настройки JVM для разных приложений различаются.
4 шаги настройки JVM
Как правило, настройку JVM можно выполнить с помощью следующих шагов:
- Анализ работы системы: анализ журналов сборщика мусора и файлов дампа, определение необходимости оптимизации и выявление узких мест;
- Определить цели количественного определения настройки JVM;
- Определить параметры настройки JVM (скорректированные в соответствии с историческими параметрами JVM);
- Поочередно определять и настраивать такие показатели, как память, задержка и пропускная способность;
- Сравните и обратите внимание на различия до и после настройки;
- Непрерывный анализ и настройка, пока не найдете подходящие параметры JVM;
- Найдите наиболее подходящие параметры, примените их ко всем серверам и отслеживайте.
В приведенных выше шагах операции некоторые шаги требуют выполнения нескольких итераций. Как правило, это начинается с удовлетворения требований программы к использованию памяти, затем следуют требования к временной задержке и, наконец, требования к пропускной способности.Необходимо постоянно оптимизировать на основе этого шага.Каждый шаг является основой для следующего шага, который необратимый.
5. Параметры JVM
Давайте посмотрим на параметры JVM JDK.
5.1 Основные параметры
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-Xms | начальный размер кучи | 1/64 памяти | По умолчанию (параметр MinHeapFreeRatio можно настроить), когда свободная память кучи меньше 40%, JVM будет увеличивать кучу до максимального предела -Xmx. |
-Xmx | максимальный размер кучи | 1/4 памяти | По умолчанию (параметр MaxHeapFreeRatio можно настроить), когда свободная память кучи больше 70%, JVM уменьшит кучу до минимального предела -Xms |
-Xmn | размер молодого поколения | Уведомление: Размер здесь (eden + 2 места для выживших) отличается от New gen, показанного в jmap -heap. Размер всей кучи = размер молодого поколения + размер старого поколения + размер постоянного поколения.После увеличения молодого поколения размер старого поколения будет уменьшен.Это значение оказывает большое влияние на производительность системы, и Sun официально рекомендует ставить до 3 для всей кучи. /8 | |
-XX:NewSize | Установить размер молодого поколения | ||
-XX:MaxNewSize | Максимум молодого поколения | ||
-XX:PermSize | Установите начальное значение постоянной генерации (perm gen) | 1/64 памяти | До JDK1.8 |
-XX:MaxPermSize | Установить максимальное постоянное поколение | 1/4 памяти | До JDK1.8 |
-Xss | размер стека на поток | После JDK5.0 размер стека каждого потока составляет 1 М. Ранее размер стека каждого потока составлял 256 КБ. Размер памяти, необходимый для большего количества потоков приложений, можно регулировать. При той же физической памяти уменьшение этого значения может привести к созданию большего количества потоков. .Однако операционная система по-прежнему имеет ограничение на количество потоков в процессе, которое не может генерироваться бесконечно.Значение опыта обычно составляет около 3000~5000 для небольших приложений.Если стек не очень глубокий, 128 КБ должно быть достаточно. для больших приложений рекомендуется использовать 256k. Этот параметр сильно влияет на производительность и требует тщательного тестирования. (Принципиальный) Объяснение параметра threadstacksize очень похожее.Официальный документ вроде не объясняет.На форуме есть такое предложение: ""-Xss переводится в флаг ВМ с именем ThreadStackSize" Вообще это значение может быть установлен. | |
-XX:ThreadStackSize | Thread Stack Size | (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.] | |
-XX:NewRatio | Отношение молодого поколения (включая Эдем и два региона Выживших) к старому поколению (исключая постоянное поколение) | -XX:NewRatio=4 указывает, что соотношение между молодым поколением и старым поколением составляет 1:4, а на молодое поколение приходится 1/5 всего стека.При установке Xms=Xmx и Xmn этот параметр не необходимо установить. | |
-XX:SurvivorRatio | Отношение размера области Эдема к площади Выжившего | Если установлено значение 8, соотношение двух областей Выживших к одной области Эдема составляет 2:8, а на одну область Выживших приходится 1/10 всего молодого поколения. | |
-XX:LargePageSizeInBytes | Размер страницы памяти нельзя ставить слишком большим, это повлияет на размер перми | =128m | |
-XX:+UseFastAccessorMethods | Быстрая оптимизация для примитивных типов | ||
-XX:+DisableExplicitGC | закрыть System.gc() | Этот параметр требует тщательного тестирования | |
-XX:+ExplicitGCInvokesConcurrent | закрыть System.gc() | disabled | Enables invoking of concurrent GC by using the System.gc() request. This option is disabled by default and can be enabled only together with the -XX:+UseConcMarkSweepGC option. |
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses | закрыть System.gc() | disabled | Enables invoking of concurrent GC by using the System.gc() request and unloading of classes during the concurrent GC cycle. This option is disabled by default and can be enabled only together with the -XX:+UseConcMarkSweepGC option. |
-XX:MaxTenuringThreshold | Максимальный возраст мусора | Если установлено значение 0, объекты молодого поколения напрямую входят в старое поколение, не проходя через область Survivor.Для приложений со многими старыми поколениями эффективность может быть повышена.Если для этого значения установлено большее значение, объекты молодого поколения Будет выполнено несколько копий в области Survivor, что может увеличить время выживания объекта в молодом поколении и повысить вероятность его переработки в молодом поколении.Этот параметр действует только в серийном GC. | |
-XX:+AggressiveOpts | ускорить компиляцию | ||
-XX:+UseBiasedLocking | Улучшение работы запирающего механизма | ||
-Xnoclassgc | Отключить сбор мусора | ||
-XX:SoftRefLRUPolicyMSPerMB | Время жизни SoftReference на мегакучу свободного места | 1s | softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap |
-XX:PretenureSizeThreshold | Объекты по размеру выделяются непосредственно в старом поколении | 0 | Единица байт Новое поколение недопустимо при использовании Parallel Scavenge GC.Другая ситуация, которая непосредственно выделяется в старом поколении, — это большой объект массива, и в массиве нет внешних ссылочных объектов. |
-XX:TLABWasteTargetPercent | TLAB в процентах от округа Эдем | 1% | |
-XX:+CollectGen0First | Запускать ли YGC в FullGC | false |
Основные параметры версии Jdk7
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-XX:PermSize | установить постоянное поколение | Версия Jdk7 и предыдущая версия | |
-XX:MaxPermSize | Установить максимальную постоянную генерацию | Версия Jdk7 и предыдущая версия |
Важные специфические параметры версии Jdk8
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-XX:MetaspaceSize | Размер метапространства | версия JDK8 | |
-XX:MaxMetaspaceSize | максимальное метапространство | версия JDK8 |
5.2, параметры параллельного коллектора
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-XX:+UseParallelGC | Полный сборщик мусора принимает параллельный MSC (это необходимо проверить) | Выберите сборщик мусора в качестве параллельного сборщика. Эта конфигурация действительна только для молодого поколения. То есть в приведенной выше конфигурации молодое поколение использует параллельный сбор, а старое поколение по-прежнему использует последовательный сбор (этот пункт подлежит проверке). ) | |
-XX:+UseParNewGC | Настроить молодое поколение на параллельный сбор | Его можно использовать одновременно с коллекцией CMS.JDK5.0 или выше, JVM установит себя в соответствии с конфигурацией системы, поэтому нет необходимости устанавливать это значение. | |
-XX:ParallelGCThreads | Количество потоков для параллельных коллекторов | Это значение лучше всего настроить равным количеству процессоров. Также применимо к CMS. | |
-XX:+UseParallelOldGC | Метод сборки мусора старого поколения — Parallel Compacting. | Это параметр параметра, который появляется в JAVA 6. | |
-XX:MaxGCPauseMillis | Максимальное время для каждой сборки мусора молодого поколения (максимальное время паузы) | Если это время не может быть соблюдено, JVM автоматически отрегулирует размер молодого поколения в соответствии с этим значением. | |
-XX:+UseAdaptiveSizePolicy | Автоматически выбирать размер области молодого поколения и соответствующий коэффициент площади выживших. | После установки этого параметра параллельный сборщик автоматически выберет размер области молодого поколения и соответствующий коэффициент площади оставшихся в живых для достижения минимального соответствующего времени или частоты сбора, указанных целевой системой. | |
-XX:GCTimeRatio | Установите время сборки мусора в процентах от времени выполнения программы. | Формула 1/(1+n) | |
-XX:+ScavengeBeforeFullGC | Вызов YGC до полного GC | true | Do young generation GC prior to a full GC. (Introduced in 1.4.1.) |
5.3 Параметры, связанные с CMS
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-XX:+UseConcMarkSweepGC | Использовать коллекцию памяти CMS | После настройки этого в тесте конфигурация -XX:NewRatio=4 недействительна, и причина неизвестна.Поэтому лучше всего использовать -Xmn для установки размера молодого поколения в это время.??? | |
-XX:+AggressiveHeap | Попытка быть оптимизацией для длительного использования большой памяти, которая использует много физической памяти, может проверять вычислительные ресурсы (память, количество процессоров), по крайней мере, 256 МБ памяти требуется для большого количества ЦП/памяти (в 1.4 .1 показал улучшение на 4-процессорных машинах) | ||
-XX:CMSFullGCsBeforeCompaction | Сколько раз выполнять сжатие памяти | Поскольку параллельный сборщик не сжимает и не организует пространство памяти, он будет генерировать «фрагментацию» после запуска в течение определенного периода времени, что снижает эффективность работы.Это значение устанавливает, сколько раз пространство памяти сжимается и организуется после запуска GC. | |
-XX:+CMSParallelRemarkEnabled | пауза нижнего маркера | ||
-XX+UseCMSCompactAtFullCollection | Сжатие старого поколения при FULL GC | CMS не перемещает память, поэтому она очень подвержена фрагментации, что приводит к нехватке памяти, поэтому в это время будет включено сжатие памяти. Хорошей практикой является увеличение этого параметра. Может повлиять на производительность, но может устранить фрагментацию | |
-XX:+UseCMSInitiatingOccupancyOnly | Запуск коллекции CMS с определением инициализации определения вручную | Предотвратите HostSPOT от запуска CMS GC сам по себе | |
-XX:CMSInitiatingOccupancyFraction=70 | Использовать CMS для сбора мусора Начать сбор CMS после 70% использования | 92 | Чтобы гарантировать, что ошибка продвижения не удалась (см. ниже), установка этого значения должна удовлетворять следующей формулеФормула расчета CMSInitiatingOccupancyFraction |
-XX:CMSInitiatingPermOccupancyFraction | Триггер, когда использование Perm Gen достигает какой скорости | 92 | |
-XX:+CMSIncrementalMode | установить в инкрементальный режим | Для случая с одним процессором | |
-XX:+CMSClassUnloadingEnabled |
5.4, дополнительная информация
имя параметра | имея в виду | По умолчанию | |
---|---|---|---|
-XX:+PrintGC | Формат вывода: [GC 118250K->113543K(130112K), 0,0094143 с] [Полный GC 121376K->10414K(130112K), 0,0650971 с] | ||
-XX:+PrintGCDetails | Формат вывода: [GC [DefNew: 8614K->781K(9088K), 0,0123035 с] 118250K->113543K(130112K), 0,0124633 с] [GC [DefNew: 8614K->8614K(9088K), 0,00006676K1 с1 с4] (121024K), 0,0433488 с] 121376K->10414K(130112K), 0,0436268 с] | ||
-XX:+PrintGCTimeStamps | |||
-XX:+PrintGC:PrintGCTimeStamps | Можно смешивать с -XX:+PrintGC -XX:+PrintGCDetails Форма вывода: 11.851: [GC 98328K->93620K(130112K), 0,0082960 с] | ||
-XX:+PrintGCApplicationStoppedTime | Вывести время, когда программа была приостановлена во время сборки мусора.Можно смешать с приведенным выше. | Форма вывода: Общее время, в течение которого потоки приложения были остановлены: 0,0468229 секунд. | |
-XX:+PrintGCApplicationConcurrentTime | Выводить время непрерывного выполнения программы перед каждой сборкой мусора.Можно смешивать с приведенным выше | Форма вывода: Время применения: 0,5291524 секунды | |
-XX:+PrintHeapAtGC | Печать подробной информации о стеке до и после GC | ||
-Xloggc:filename | Запишите соответствующую информацию журнала в файл для анализа. | ||
-XX:+PrintClassHistogram | garbage collects before printing the histogram. | ||
-XX:+PrintTLAB | Просмотр использования пространства TLAB | ||
XX:+PrintTenuringDistribution | Просмотр порога нового жизненного цикла после каждого минорного GC | Желаемый размер оставшегося в живых 1048576 байт, новое пороговое значение 7 (максимум 15) новое пороговое значение 7 — это пороговое значение 7 для определения нового периода выживания. |
6. Основные инструменты
6.1, инструменты JDK
JDK поставляется со многими инструментами мониторинга производительности, которые мы можем использовать для мониторинга системы и устранения проблем с производительностью памяти.
6.2, инструменты командной строки Linux
При мониторинге производительности и устранении неполадок это часто выполняется в сочетании с собственными инструментами командной строки операционной системы.
Заказ | иллюстрировать |
---|---|
top | Отображение в режиме реального времени использования ЦП, использования памяти и загрузки системы выполняющимися процессами. |
vmstat | Мониторинг виртуальной памяти операционной системы, процессов и активности ЦП |
pidstat | Отслеживайте переключение контекста указанного процесса |
iostat | Мониторинг дискового ввода-вывода |
Существуют и другие сторонние инструменты мониторинга, которые также являются мощными инструментами для анализа производительности и устранения неполадок, напримерMAT,GChisto,JProfiler,arthas.
7. Общие стратегии настройки
Здесь еще необходимо упомянуть о том, что необходимо вовремя определить необходимость настройки JVM, и не попасть в «барьер знаний». оптимизатор по-прежнему является первым выбором.
7.1, выберите подходящий сборщик мусора
С одним ядром ЦП, нет сомнений, что последовательный сборщик мусора — ваш единственный вариант.
Многоядерный ЦП, сосредоточьтесь на пропускной способности, затем выберите комбинацию PS+PO.
Многоядерный ЦП, обеспокоенный временем паузы пользователя, JDK версии 1.6 или 1.7, затем выберите CMS.
Многоядерный ЦП, обратите внимание на время паузы пользователя, JDK1.8 и выше, доступная память JVM превышает 6 ГБ, затем выберите G1.
Конфигурация параметров:
//设置Serial垃圾收集器(新生代)
开启:-XX:+UseSerialGC
//设置PS+PO,新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器
开启 -XX:+UseParallelOldGC
//CMS垃圾收集器(老年代)
开启 -XX:+UseConcMarkSweepGC
//设置G1垃圾收集器
开启 -XX:+UseG1GC
7.2, отрегулируйте размер памяти
Феномен: Частота сбора мусора очень высока.
Причина: если памяти слишком мало, это вызовет частую сборку мусора, чтобы освободить достаточно места для создания новых объектов, поэтому эффект от увеличения размера кучи памяти очень очевиден.
Примечание. Если число сборок мусора очень частое, но каждый раз может быть утилизировано очень мало объектов, то в это время память не слишком мала, но это может быть утечка памяти, которая препятствует восстановлению объектов, что приводит к частым ГК.
Конфигурация параметров:
//设置堆初始值
指令1:-Xms2g
指令2:-XX:InitialHeapSize=2048m
//设置堆区最大值
指令1:`-Xmx2g`
指令2: -XX:MaxHeapSize=2048m
//新生代内存配置
指令1:-Xmn512m
指令2:-XX:MaxNewSize=512m
7.3 Установите время паузы, соответствующее ожиданиям
Явление: Программа косвенно зависла
Причина: Если нет точной настройки времени паузы, а сборщик мусора ориентирован на пропускную способность, время сборки мусора будет нестабильным.
Примечание: не устанавливайте нереалистичное время паузы.Чем короче однократное время, тем больше времени GC требуется для сбора исходного количества мусора.
Конфигурация параметров:
//GC停顿时间,垃圾收集器会尝试用各种手段达到这个时间
-XX:MaxGCPauseMillis
7.4 Отрегулируйте соотношение размера области памяти
Феномен: ГК часто встречается в одной области, в то время как другие являются нормальными.
Причина: если в соответствующей области недостаточно места, требуется частая сборка мусора для освобождения места, а соотношение размеров соответствующей области может быть скорректировано, если память кучи JVM не может быть увеличена.
Примечание. Возможно, не из-за нехватки места, а из-за невозможности восстановления памяти из-за утечек памяти. Это приводит к частым GC.
Конфигурация параметров:
//survivor区和Eden区大小比率
指令:-XX:SurvivorRatio=6 //S区和Eden区占新生代比率为1:6,两个S区2:6
//新生代和老年代的占比
-XX:NewRatio=4 //表示新生代:老年代 = 1:4 即老年代占整个堆的4/5;默认值=2
7.5. Отрегулируйте возраст возраста старения объекта
Феномен: Старость часто является GC, и каждый раз собирается много объектов.
Причина: если возраст поощрения мал, объекты нового поколения вскоре перейдут к старому поколению, в результате чего в старом поколении появится больше объектов.На самом деле, эти объекты можно восстановить за короткий период времени.В настоящее время, генерация обновления объекта может быть скорректирована.Возраст, чтобы объекты не так легко входили в старость, чтобы решить проблему частого GC из-за нехватки места в старости.
Примечание: После увеличения возраста время этих объектов в молодом поколении станет больше, что может привести к увеличению частоты GC молодого поколения, и время GC нового поколения этих объектов также может быть больше если объекты копируются часто.
Параметры конфигурации:
//进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,默认值7
-XX:InitialTenuringThreshol=7
7.6. Настройка стандарта больших объектов
Феномен: старый частый сборщик мусора, каждый раз восстанавливается много объектов, и объем отдельных объектов велик.
Причина: если большое количество больших объектов напрямую отнесено к старому возрасту, старый возраст легко заполняется и вызывает частый GC.Можно установить стандарт для объектов, чтобы они напрямую попадали в старый возраст.
Примечание: эти большие объекты могут увеличить частоту и время GC молодого поколения после входа в молодое поколение.
Параметры конфигурации:
//新生代可容纳的最大对象,大于则直接会分配到老年代,0代表没有限制。
-XX:PretenureSizeThreshold=1000000
7.7. Отрегулируйте время запуска GC
Явление: CMS, G1 часто Full GC, и программа серьёзно зависает.
Причина: Некоторые этапы GC G1 и CMS выполняются одновременно.Бизнес-поток и поток сборки мусора работают вместе, а это значит, что бизнес-поток будет генерировать новые объекты в процессе сборки мусора, поэтому необходимо резервировать часть пространство памяти для GC.Для размещения вновь сгенерированных объектов, если места в памяти недостаточно для размещения вновь сгенерированных объектов в это время, то JVM остановит параллельный сбор и приостановит все бизнес-потоки (STW), чтобы обеспечить нормальную работу мусора коллекция. В это время вы можете настроить время запуска GC (например, запуск GC, когда старый занимает 60%), чтобы можно было зарезервировать достаточно места для объектов, созданных бизнес-потоком, чтобы иметь достаточно места для выделения.
Примечание. Ранний запуск GC повысит частоту GC старого поколения.
Параметры конфигурации:
//使用多少比例的老年代后开始CMS收集,默认是68%,如果频繁发生SerialOld卡顿,应该调小
-XX:CMSInitiatingOccupancyFraction
//G1混合垃圾回收周期中要包括的旧区域设置占用率阈值。默认占用率为 65%
-XX:G1MixedGCLiveThresholdPercent=65
7.8 Настройка размера локальной памяти JVM
Явление: время GC, время и восстановленные объекты в норме, памяти в куче достаточно, но сообщается об OOM
Причина: В дополнение к памяти кучи, JVM имеет дополнительную память кучи. Эта память также называется локальной памятью. Однако, когда этой области памяти недостаточно, она не будет активно запускать GC. памяти недостаточно, будет сообщено об исключении OOM напрямую.
Примечание: Когда локальная память ненормальна, в дополнение к описанному выше явлению, ненормальной информацией может быть OutOfMemoryError: Прямая буферная память. В дополнение к настройке размера локальной памяти решение также может быть перехвачено, когда возникает это исключение, и вручную запускает GC (System.gc()).
Параметры конфигурации:
XX:MaxDirectMemorySize
8. Пример настройки JVM
Вот несколько примеров настройки JVM, взятых из Интернета:
8.1 После скачка посещаемости веб-сайта страница ответа веб-сайта работает очень медленно
1. Предположение о проблеме: скорость тестирования относительно высока в тестовой среде, но становится медленнее, когда она достигает рабочей среды, поэтому предполагается, что бизнес-поток может быть приостановлен из-за сборки мусора.
2. Позиционирование: чтобы подтвердить правильность предположения, онлайн-команда jstat -gc показывает, что частота GC JVM очень высока, а время, занимаемое GC, очень велико, поэтому основной вывод заключается в том, что поскольку частота GC очень высок, это приводит к бизнес-тредам Частые паузы, что приводит к медленному отклику веб-страницы.
3. Решение: поскольку трафик веб-страницы очень высок, скорость создания объектов очень высока, что приводит к легкому заполнению динамической памяти и частому сбору мусора, поэтому проблема здесь в том, что память нового поколения слишком мала. , так что тут достаточно увеличить память JVM, так что предварительно С исходной 2G памяти до 16G памяти.
4. Вторая проблема: После увеличения памяти обычные запросы действительно стали быстрее, но возникла другая проблема, то есть время от времени будут периодические зависания, причем время единичного зависания значительно больше, чем раньше. .
5. Предположение о проблеме: предыдущая оптимизация увеличила объем памяти, поэтому предположение может быть связано с увеличением объема памяти, что приводит к увеличению времени для одного GC и косвенному замораживанию.
6. Позиционирование: по команде jstat -gc по-прежнему видно, что количество FGC не очень велико, но время, затраченное на FGC, очень велико.По логу GC, время на один FGC может достигать десятков секунды.
7. Решение. Поскольку JVM по умолчанию использует комбинацию PS+PO, этапы маркировки и сбора мусора PS+PO являются STW, поэтому после увеличения памяти время, необходимое для сборки мусора, становится больше, поэтому здесь чтобы один сборщик мусора не занимал слишком много времени, необходимо заменить параллельный сборщик.Поскольку текущая версия JDK — 1.7, окончательно выбирается сборщик мусора CMS, а ожидаемое время паузы устанавливается в соответствии с предыдущей сборкой мусора.Веб-сайт больше не застрял.
8.2. OOM, вызванный экспортом данных в фоновом режиме
**Описание проблемы:** Фоновая система компании время от времени вызывает исключения OOM и переполнение динамической памяти.
1. Поскольку это случайно, в первый раз я просто подумал, что это вызвано недостаточным объемом памяти кучи, поэтому в одностороннем порядке увеличил память кучи с 4G до 8G.
2. Но проблема так и не решена, мы можем только начать с информации о памяти кучи, и получить файл дампа памяти кучи, включив параметр -XX:+HeapDumpOnOutOfMemoryError.
3. VisualVM анализирует файл дампа кучи. Через VisualVM видно, что объект, который занимает больше всего памяти, это объект String. Изначально я хотел отследить объект String, чтобы найти его ссылку, но файл дампа слишком велик, и он всегда застревает при отслеживании его.Это нормально, что объекты String занимают больше.Сначала я не думал, что это проблема, поэтому искал точку прорыва в информации о потоке.
4. С помощью анализа потоков я сначала обнаружил несколько запущенных бизнес-потоков, а затем проследил за бизнес-потоками один за другим, чтобы прочитать код, и обнаружил, что существует метод, привлекший мое внимание, — экспорт информации о заказе.
5. Поскольку метод экспорта информации о заказе может иметь десятки тысяч томов данных, информация о заказе должна быть сначала запрошена из базы данных, а затем информация о заказе будет сгенерирована в Excel.Этот процесс будет генерировать большое количество объектов String .
6. Дабы проверить свою догадку, я приготовился зайти в бэкграунд для проверки, в итоге в ходе проверки обнаружил, что интерфейс кнопки заказа везде не делает интерактивное событие серого цвета кнопку после нажатия.В результате кнопку можно нажимать все время,потому что данные о заказе на экспорт изначально очень медленные.Пользователи,использующие ее,могут обнаружить,что страница долго не отвечает после нажатия,и результат В результате в фон уходит большое количество запросов, в куче памяти генерируется большое количество объектов заказа и объектов EXCEL, выполнение метода очень медленное, в результате эти объекты не могут быть восстановлены для период времени, что в конечном итоге приводит к переполнению памяти.
7. Проблема решается легко, когда вы ее знаете.В итоге никакие параметры JVM не были скорректированы, но к кнопке заказа экспорта внешнего интерфейса было добавлено серое состояние.После ответа внутреннего интерфейса кнопку можно щелкнул, а затем запрос информации о заказе сокращает ненужные поля, чтобы уменьшить размер формируемого объекта, и проблема решена.
8.3. ЦП системы настолько высок, что данные одного кэша слишком велики.
1. После выпуска системы обнаруживается, что загрузка ЦП увеличивается до 600%.После обнаружения этой проблемы первое, что нужно сделать, это определить, какое приложение занимает больше всего ЦП, и найти соответствующее приложение Java, которое занимает 600 % ресурса ЦП через top.
2. Если ЦП приложения слишком высок, в основном можно определить, что это может быть вызвано конкуренцией ресурсов блокировки или частым сборщиком мусора.
3. Итак, сначала подготовьтесь к проверке ситуации с сборщиком мусора. Если сборщик мусора в норме, проверьте с точки зрения потока. Сначала используйте команду jstat -gc PID, чтобы распечатать информацию о сборщике мусора. В результате статистика сборщика мусора полученные явно ненормальны, и приложение работает.В случае всего нескольких минут время GC заняло 482 секунды, так что это, очевидно, высокая загрузка ЦП, вызванная частым GC.
4. Если проблема GC локализована, то следующим шагом является поиск причины частого GC, поэтому она может быть обнаружена с двух сторон, это может быть место, где часто создаются объекты, или утечка памяти, которая предотвращает переработку памяти.
5. Согласно этой идее, мы решили сбросить информацию о памяти кучи и посмотреть.Используйте команду jmap -dump для дампа информации о памяти кучи (используйте эту команду с осторожностью, если пространство кучи памяти велико, иначе она легко влияют на приложение, потому что объем нашей динамической памяти составляет всего 2 ГБ, поэтому я не рассматривал эту проблему).
6. После дампа информации о памяти кучи использовать visualVM для оффлайн анализа.Сначала найти объект который занимает больше всего памяти,и результат занимает третье место.Видно,что бизнес ВО занимает около 10% пространства кучи памяти.Очевидно , этот объект проблематичен.
7. Соответствующий бизнес-код находится через бизнес-объект, а подозрительная точка обнаруживается посредством анализа кода.Этот бизнес-объект представляет собой объект, созданный путем просмотра новостной информации.Для повышения эффективности запроса новостная информация сохраняется в кеш Redis.Внутри каждый вызов информационного интерфейса получается из кеша.
8. Нет проблем с сохранением новостей в кэше redis, проблема в том, что в ключе хранится более 50 000 единиц новостных данных, что приведет к сохранению более 50 000 единиц новостей из redis при каждом запросе новости. называется интерфейс Выньте все фрагменты данных, а затем выполните фильтрацию и разбиение по страницам, чтобы вынуть 10 фрагментов и вернуть их во внешний интерфейс. Более 50 000 фрагментов данных означает, что будет сгенерировано более 50 000 объектов, каждый объект имеет размер около 280 байт, а 50 000 объектов имеют 13,3 млн, что означает, что только один просмотр новостной информации будет генерировать не менее 13,3 млн объектов. пока количество одновременных запросов достигает 10, 133M объектов будут генерироваться каждую секунду, и такие большие объекты будут напрямую выделены для старости.В этом случае старая память 2G будет заполнена всего за несколько секунд. тем самым запуская GC.
9. Зная проблему, ее легко решить. Проблема вызвана тем, что один кеш слишком велик, поэтому вам нужно только уменьшить кеш. Здесь вам нужно только кешировать кеш на уровне страниц. Каждый ключ кэширует 10 фрагментов данных, так как данные возвращаются на страницу внешнего интерфейса 1, поэтому каждый раз, когда вы запрашиваете информацию о новостях, из кэша будет извлекаться только 10 фрагментов данных, что позволяет избежать этой проблемы.
8.4, ЦП часто 100% проблемное место
Анализ проблемы: Высокая загрузка ЦП должна заключаться в том, что программа долгое время занимала ресурсы ЦП.
1. Итак, сначала вам нужно выяснить, какой из них занимает больше всего ЦП.
top 列出系统各个进程的资源占用情况。
2. Затем выяснить, какой поток занимает больше всего ЦП в соответствующем процессе.
top -Hp 进程ID 列出对应进程里面的线程占用资源情况
3. Найдя соответствующий идентификатор потока, распечатайте информацию о стеке соответствующего потока.
printf "%x\n" PID 把线程ID转换为16进制。
jstack PID 打印出进程的所有线程信息,从打印出来的线程信息中找到上一步转换为16进制的线程ID对应的线程信息。
4. Наконец, найдите конкретный бизнес-метод в соответствии с информацией о стеке потока и найдите проблему с помощью логики кода.
查看是否有线程长时间的watting 或blocked
如果线程长期处于watting状态下, 关注watting on xxxxxx,说明线程在等待这把锁,然后根据锁的地址找到持有锁的线程。
8.5. Расположение проблемы с нехваткой памяти
Анализ: если в процессе Java возникает переполнение памяти, это обычно вызвано созданием большого количества объектов.Постоянно высокий уровень указывает на то, что сборка мусора не может угнаться за скоростью создания объекта или объект не может быть восстановлен из-за утечки памяти.
1. Сначала наблюдайте за ситуацией со сборкой мусора
jstat -gc PID 1000 查看GC次数,时间等信息,每隔一秒打印一次。
jmap -histo PID | head -20 查看堆内存占用空间最大的前20个对象类型,可初步查看是哪个对象占用了内存。
Если количество GC каждый раз частое, а объем памяти, восстанавливаемый каждый раз, нормальный, это означает, что использование памяти всегда велико, потому что скорость создания объекта высока; если память, собираемая каждый раз, очень мала, вероятно, быть вызвано утечками памяти. Он никогда не был переработан.
2. Экспорт моментального снимка файла памяти кучи
jmap -dump:live,format=b,file=/home/myheapdump.hprof PID dump堆内存信息到文件。
3. Используйте VisualVM для анализа файла дампа в автономном режиме, найдите объект с высоким потреблением памяти, а затем найдите расположение бизнес-кода, создавшего объект, и найдите конкретные проблемы в коде и бизнес-сценариях.
8.6. Частый полный GC в системе платформы анализа данных
Платформа в основном проводит регулярный анализ и статистику поведения пользователя в приложении, а также поддерживает экспорт отчетов с использованием алгоритма CMS GC.
За время использования аналитик данных обнаружил, что системная страница часто зависала при открытии.С помощью команды jstat было установлено, что около 10% выживших объектов уходили в старость после каждого Young GC.
Получается, что из-за того, что места в области Survivor слишком мало, уцелевшие объекты нельзя размещать в области Survivor после каждого GC Young, и они входят в старость заранее.
Увеличивая область Survivor, область Survivor может вместить выжившие объекты после Young GC.Объекты в области Survivor проходят через несколько Young GC и достигают возрастного порога, прежде чем войти в старость.
После корректировки уцелевшие объекты, входящие в старое поколение, после каждого Young GC стабильно работают всего несколько сотен Кб, а частота Full GC сильно снижается.
8.7. Сервисный стыковочный шлюз OOM
Шлюз в основном потребляет данные Kafka, выполняет обработку и расчет данных, а затем перенаправляет их в другую очередь Kafka.OOM возникает, когда система работает в течение нескольких часов, а OOM возникает через несколько часов после перезапуска системы.
Память кучи выгружается через jmap, а причина выясняется после анализа eclipse MAT tool: В коде асинхронно в логе печатаются топик-данные определенного бизнеса Kafka.Объем бизнес-данных большой, и в памяти накапливается большое количество объектов, ожидающих печати, что приводит к OOM.
8.8 Система аутентификации часто запускает полный сборщик мусора в течение длительного времени
Система предоставляет различные услуги аутентификации учетной записи для внешнего мира.При ее использовании обнаруживается, что система часто недоступна.Благодаря мониторингу платформы мониторинга Zabbix обнаружено, что в системе часто происходит полный GC в течение длительного времени, и память кучи старого поколения обычно не заполняется при ее срабатывании System.gc() вызывается в бизнес-коде.
Ссылаться на:
[1]: Чжоу Чжимин отредактировал «Глубокое понимание виртуальной машины Java: расширенные функции и лучшие практики JVM».
[2]: «Практическая диагностика ошибок JVM виртуальной машины JAVA и оптимизация производительности»
【3】:Подробная настройка производительности JVM
【4】:Как разумно спланировать настройку производительности jvm
【5】:Относительно принципа GC и практики настройки производительности достаточно прочитать эту статью
【6】:Практика настройки производительности Java-приложений
【7】:JVM в действии: стратегии настройки JVM
【8】:Требуют ли общие проекты Java настройки JVM?
【9】:Интерпретация параметров Java8 JVM
【10】:Настройки параметров JVM - настройки параметров jdk8
【11】:Серия вопросов интервью JVM: общие параметры конфигурации JVM и общие стратегии настройки GC