Каждый день GC выполняется в одно и то же время

#jboss #garbage-collection

#jboss #сбор мусора

Вопрос:

На моем сервере каждый день в 3:00 работает GC, и пространство кучи заполняется мгновенно.

Это вызывает сбой сайта. КАКИЕ-либо входные данные?

ниже приведены мои настройки JVM.Я использую сервер JBOSS.

-Dprogram.name=run.sh -сервер -Xms1524m -Xmx1524m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -XX:NewSize=512m -XX:MaxNewSize=512m -Djava.net.preferIPv4Stack=true -XX:MaxPermSize=512m -XX: UseConcMarkSweepGC -XX: CMSClassUnloadingEnabled -Djavax.net.ssl.trustStorePassword=changeit -Dcom.sun.management.jmxremote.port=8888 -Djava.rmi.server.hostname=192.168.100.140 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote

Любые предложения действительно полезны..

Комментарии:

1. У вас есть что-нибудь запланированное для запуска в 3 часа ночи?

2. Нет .. мы отслеживали журналы, и никакой другой планировщик не запущен.. Даже я проверил, как я перезапустил сервер в 2:30 утра, чтобы куча была очищена. до 3:00 утра куча составляет до 400 МБ. В 3:00 внезапно запускается GC, и все пространство мгновенно заполняется.

3. Ниже приведены выходные данные gc.log о сбое GC. Любые входные данные действительно полезны. 34277.999: 34284.652: [CMS-concurrent-preclean-start] 34284.758: [GC 34284.758: [Обновление (сбой продвижения): 523392K-> 523392K (523840K), 0,8095230 секунд] 34285.568: [CMS34286.158: [CMS-concurrent-preclean: 0,662 / 1,506секунды] (сбой параллельного режима): 998786K-> 984155K (1036288K), 6.4504900 секунд] 1517815K-> 984155K (1560128K), 7.2603450 секунд]

Ответ №1:

(Это получилось несколько длинным; в конце есть фактическое предложение по исправлению.)

Очень, очень кратко, сборка мусора при использовании -XX: UseConcMarkSweepGC работает следующим образом:

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

Когда объекты сохранились (все еще доступны) молодого поколения, они получают повышение до «старого поколения» (старое поколение).

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

С CMS (-XX: UseConcMarkSweepGC) работа по сжатию старого поколения в основном выполняется параллельно (то есть выполняется в фоновом режиме, когда приложение не приостановлено). Эта работа также не уплотняется; она больше похожа на malloc() / free(), и вы подвержены фрагментации.

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

Два основных недостатка заключаются в том, что:

  • Вы подвержены фрагментации, потому что старое поколение не уплотняется.
  • Если вы не завершите параллельный цикл сбора данных до заполнения старого поколения или если фрагментация предотвращает выделение, результирующая полная коллекция всей кучи не будет параллельной, как с коллектором по умолчанию. Т. е. Используется только один процессор. Это означает, что когда / если вы выполняете полную сборку мусора, пауза будет длиннее, чем при использовании сборщика по умолчанию.

Теперь … ваши журналы. «Сбой параллельного режима» предназначен для сообщения о том, что одновременная работа по разметке / развертке не была завершена вовремя для другого GC молодого поколения, который должен продвинуть выжившие объекты в старое поколение. «Сбой продвижения» скорее означает, что во время продвижения с молодого поколения на старое поколение объект не смог быть выделен в старом поколении из-за фрагментации.

Если вы не столкнулись с реальной ошибкой в JVM, внезапное увеличение использования кучи почти наверняка связано с вашим приложением, JBoss или каким-либо внешним объектом, действующим в вашем приложении. Так что я не могу с этим помочь. Однако, вероятно, происходит сочетание двух вещей:

  1. Всплеск активности приводит к слишком быстрому увеличению использования кучи, чтобы одновременная коллекция завершалась вовремя.
  2. Старое поколение слишком фрагментировано, что вызывает проблемы, особенно когда старое поколение почти заполнено.

Я должен также отметить, что поведение CMS по умолчанию заключается в попытке отложить одновременные коллекции как можно дольше (но не слишком долго) по соображениям производительности. Чем позже это произойдет, тем эффективнее (с точки зрения использования ЦП) коллекция. Однако компромисс заключается в том, что вы увеличиваете риск не закончить вовремя (что, опять же, приведет к полному GC и длительной паузе). Это также должно (я не проводил здесь эмпирических тестов, но это само собой разумеется) привести к тому, что фрагментация станет более серьезной проблемой; в основном, чем более полным является старое поколение при продвижении объекта, тем больше вероятность того, что продвижение объекта усугубит проблемы фрагментации (слишком долго, чтобы вдаваться в подробностиподробности здесь).

В вашем случае я бы сделал две вещи:

  1. Продолжайте выяснять, что вызывает активность. Я бы сказал, что маловероятно, что это ошибка GC / JVM.
  2. Переконфигурируйте JVM, чтобы запускать параллельные циклы сбора раньше, чтобы избежать переполнения кучи настолько, что фрагментация становится особенно серьезной проблемой, и дает ей больше времени для завершения даже во время ваших внезапных всплесков активности.

Вы можете выполнить (2) проще всего, используя параметры JVM

  • -XX:CMSInitiatingOccupancyFraction=75
  • -XX: UseCMSInitiatingOccupancyOnly

чтобы явно заставить JVM запустить цикл CMS при определенном уровне использования кучи (в этом примере 75% — вам может потребоваться изменить это; чем ниже процент, тем раньше он начнется).

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

Комментарии:

1. Scode.. Большое вам спасибо.. Это дало мне полное представление о GC. Я протестирую это и опубликую вам обновление. Другое дело, что иногда при обычном запуске GC наши системные потоки быстро увеличиваются.. Есть предложения??

2. Под обычным вы подразумеваете частые коллекции молодого поколения? Вы говорите, что каждый раз видите всплеск потоков, за которым следует уменьшение до следующего? Если это так, то для меня это звучит как наращивание, вызванное тем, что все, что работало, было «поставлено в очередь» (например, на входящий tcp-сокет, accept () backlog и т. Д.) На время GC. Но это серьезные предположения, поскольку я ничего не знаю о ситуации.

3. мы также заметили, что при запуске gc загрузка процессора внезапно увеличилась до 90, и она снижается после завершения работы gc. Это не для всех коллекций молодого поколения, а только для некоторых коллекций. Есть ли какие-либо конфигурации, которые я пропускаю?

4. Описание gc молодого поколения неверно. Молодое поколение gc является сборщиком копий. Все потоки мутаторов остановлены, все живые объекты в eden и из космоса копируются в to-space, а некоторые объекты могут быть переведены в постоянное пространство. Затем потоки перезапускаются. Обратите внимание, что копирующий сборщик по умолчанию является уплотняющим сборщиком.