Место преступления:
Однажды в 20-х годах нашей эры я неторопливо завтракал в компании, и вдруг с моего мобильного телефона пришло оповещение приложения! ! ! Откройте его и посмотрите:Использование устаревшей памяти приложения превышает 95%В поле зрения появилось несколько крупных символов, и я так испугалась, что быстро уронила мясные булочки в руку и быстро проверила!
Следующее изображение является свидетельством преступления, которое было повторно снято из мониторинга приложения после решения проблемы.Очевидно, что старость приложения часто выполняет полную сборку мусора в течение определенного периода времени, а максимальная точка памяти завис на 100%.
Процесс охоты:
Кхм, как зрелый java siege lion, столкнувшись с вором вроде oom, автор естественно сохранял спокойное лицо (вообще-то я сильно паниковал. такой горшок).
В то время первой реакцией было сначала проконсультироваться с коллегами по эксплуатации и обслуживанию и обнаружить, что на платформе мониторинга нет встроенного инструмента анализа памяти, и необходимо выполнить анализ дампа самостоятельно. В данном случае могу только стиснуть зубы.Про подключение к трамплину и вход в продакшен автор ничего не говорит.jpsНайдите идентификатор процесса текущего Java-приложения, еще один трюкjmap -dump:format=b,file=filename pid, я думал, что когда я получу файл дампа, я обязательно исправлю твоего убийцу. Спустя долгое время ~~~ 10 минут я наконец-то получил файл дампа (здесь опущены всякие сообразительности и храбрости с экспортом файлов производственной среды).
Автору не терпится достать левый и правый скальпели (тот, что идет в комплекте с javavisualvmс известным программным обеспечением для внешнего анализаmat), готовый к вскрытию файла дампа. Ведь когда я впервые воспользовался ножом, я полтора раза не умел пользоваться рукоятью, я действительно потерял морду своего осадного льва! После долгого метания я наконец-то открыл мат и загрузил файл дампа. (Mac, использующий мат, может иногда сталкиваться с ямами, которые не запускаются, я не буду здесь вдаваться в подробности, пожалуйста, изучите себя / Google)
Первый нож, вскрывающий труп, обнажает окровавленные внутренние органы, как показано ниже:
Потяните, чтобы аккумулировать объекты в элементе дерева dominator, в котором для нас указана структура памяти этого объекта asyncAppender. Как и ожидалось, инфраструктура журналирования будет использовать очередь для кэширования объектов loggingEvent, и каждый раз, когда вызывается вывод журнала, он будет заключен в loggingEvent и кэширован. Из первой и второй точек на приведенном выше рисунке видно, что эта очередь кэша логов занимает очень большой объем памяти, и только на его объект loggingEvent приходится около 23% памяти, боже мой. Окно наблюдения инспектора в третьей точке на приведенном выше рисунке может отображать конкретное содержимое этого объекта, поэтому мы перехватили сообщение первых двух объектов loggingEvent с наибольшей долей, чтобы увидеть, каково содержимое этого журнала.
Поставить в известность:
Простое oom действительно не ускользнуло от взора автора. Окончательные качественные причины этого случая таковы:Из-за ошибки проектирования sql объем данных пакетного запроса огромен, что превышает предел передачи dubbo, поэтому выдается исключение и записывается журнал. Объект лога содержит огромное количество специфической информации о возвращаемом запросом объекте и выбрасывается в очередь асинхронного лога, лог не успел сбросить на диск, а память уже лопнула, и oom alarm! !При последующей оптимизации, помимо модификации sql, оптимизируются условия пакетного запроса, а в конфигурацию logback добавляется ограничение на максимальную длину лога для предотвращения возникновения oom, вызванного печатью лога.