Настройки сборки мусора с OpenJDK8 - PullRequest
0 голосов
/ 10 мая 2018

Мне нужна помощь в настройке одного из наших микросервисов.

мы запускаем микросервис на основе Spring (Spring Integration, Spring Data JPA) на простом сервере в контейнере OpenJDK8. Мы также используем Месосферу в качестве нашей платформы для оркестровки контейнеров.

Приложение принимает сообщения от IBM MQ, выполняет некоторую обработку, а затем сохраняет обработанный вывод в БД Oracle.

Мы заметили, что в какой-то момент 2 мая обработка очереди остановилась из нашего приложения. Наша команда MQ все еще видела, что были открытые соединения с очередью, но приложение просто больше не читало. Это не умерло полностью, поскольку Apache HealthCheck, который поражает DCOS, все еще показывает, как здоровый.

enter image description here Мы используем AppD для мониторинга производительности, и мы увидели, что в тот же день была выполнена сборка мусора, и приложение никогда не получало сообщения из очереди. На приведенном выше графике показано количество времени, затраченного на сбор данных в разные даты.

Как часть Java Opts, которую мы используем для запуска приложения, мы заявляем

-Xmx1024m

Резервирование мезосферы для каждого из этих микросервисов показано ниже

enter image description here

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

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

Приветствие Kris

Ответы [ 5 ]

0 голосов
/ 12 мая 2018

Я только что видел ваши комментарии о процессоре

увеличить выделение ЦП с 0,5 до 1,25 ЦП

Пожалуйста, имейте в виду, что для выполнения параллельного GC вам нужно как минимум два ядра. Я думаю, что в вашей конфигурации вы используете последовательный сборщик, и в настоящее время нет причин использовать последовательный сборщик мусора, когда вы можете использовать несколько ядер. Рассматривали ли вы попробовать по крайней мере два ядра? Я часто использую четыре как минимальное число для своих серверов приложений по производительности и производительности.

Вы можете увидеть больше информации здесь:

На машине с N аппаратными потоками, где N больше 8, параллельный сборщик использует фиксированную долю N в качестве числа потоков сборщика мусора. Фракция составляет приблизительно 5/8 для больших значений N. При значениях N ниже 8 используемое число равно N. На выбранных платформах доля уменьшается до 5/16. Конкретное количество потоков сборщика мусора можно настроить с помощью параметра командной строки (который будет описан ниже). На хосте с одним процессором параллельный коллектор, скорее всего, не будет работать так же хорошо, как последовательный коллектор из-за издержек, необходимых для параллельного выполнения (например, синхронизации) . Однако при запуске приложений с кучами среднего и большого размера он обычно превосходит последовательный коллектор на машинах с двумя процессорами на скромную величину и обычно работает значительно лучше, чем последовательный коллектор, когда доступно более двух процессоров.

Источник: https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/parallel.html

1020 * Рауль *

0 голосов
/ 11 мая 2018

Спасибо за ваш вклад, ребята. Мы будем пытаться увеличить распределение ЦП с 0,5 до 1,25 ЦП и выполнить еще один раунд тестов NFT.

Мы попытались запустить команду ниже

jmap -dump:format=b,file=$FILENAME.bin $PID

чтобы получить дамп кучи, но утилита отсутствует в контейнере OpenJDK8 по умолчанию.

0 голосов
/ 10 мая 2018

Я не думаю, что здесь происходит сборка мусора, или что вы должны пытаться исправить это путем настройки параметров GC.

Я думаю, что это одна из двух вещей:

  1. Совпадение. Корреляция (для отдельной точки данных), которая не подразумевает причинность.

  2. Что-то о сборке мусора или событии, вызвавшем сборку мусора, вызвало что-то в вашем приложении.

Для последнего существует множество возможностей. Но одна вещь, которая приходит на ум, заключается в том, что что-то (например, запрос) заставило поток приложения выделить действительно большой объект. Это вызвало полный сборщик мусора в попытке найти место. GC не удалось; то есть, после того, как GC сделал все возможное, еще не было достаточно места. Это затем превратилось в OOME, которое убило нить.

Если (гипотетический) поток, который был уничтожен OOME, был критически важным для приложения операции, а остальная часть приложения не «заметила», что оно умерло, то приложение в целом сломалось бы.

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

0 голосов
/ 11 мая 2018

Что касается графика ApppD? Это время в секундах? Сколько у вас Full GC? Возможно, вам следует включить журнал для сборщика мусора.

0 голосов
/ 10 мая 2018

Вы должны проверить свой код.

Операция GC запускает операцию STW (Stop The World), которая блокирует все потоки, созданные в вашем коде. Но STW не влияет на состояние выполнения кода.

Но gc повлияет на логику вашего кода, если вы будете использовать System.currentTimeMillis для управления логикой выполнения кода.

Операция gc также повлияет на ненадежную ссылку, если вы используете WeakReference, SoftReference, WeakHashMap, после полного gc эти компоненты могут изменить свое поведение.

Выполнена полная операция gc, и освобожденная память не позволяет вашему коду выделять новый объект, ваш код выдаст исключение OutOfMembryException, которое прервет выполнение вашего кода.

Я думаю, что вы должны сделать сейчас:

Сначала проверьте 'GC Cause', чтобы определить, произошел ли полный вызов gc в System.gc() call или Allocate failed.

Тогда, если GC Cause равно System.gc(), вам следует проверить ненадежную ссылку, используемую в вашем коде.

Наконец, если причиной GC является Allocate failed, вы должны проверить свой журнал, чтобы определить, произошла ли в вашем коде OutOfMembryException, если случится, вы должны выделить больше памяти, чтобы избежать OutOfMembryException.

В качестве подсказки НЕ СЛЕДУЕТ хранить сообщение mq в памяти приложения микросервиса. В большинстве случаев источником проблемы с gc является плохая практика в вашем коде.

...