Феномен
Ранним утром одного дня мобильный телефон внезапно подал сигнал тревоги, и уровень использования памяти определенной машины в сети превысил 90%. На следующее утро был релиз, память не работала, в течение дня проблема не исследовалась. В вечерний пиковый период я получил сигнал тревоги, что вызов памяти превысил 90%, и через некоторое время определенный аппарат на линии завис.
сохранить на сайте
В это время, после того как машина зависнет, она немедленно перезапустится и выгрузит информацию о памяти другой машины.
jmap -dump:format=b,file=文件名 [pid]
Обнаружил небольшой эпизод во время процесса дампа и не смог его сбросить.
Эта ситуация вызвана тем, что пользователь, не являющийся текущим потоком, добавил команду передsudo -u 用户
Просто
Также сохраните информацию о цепочке
sudo -u jetty jstack pid > /tmp/jstack2018-04-18.txt
выявить проблему
Просмотр системных журналов сервера
cat /var/log/messages
см. вышеKilled process 7364, UID 502, (java) total-vm:10511252kB, anon-rss:7489308kB
Память Java использует более 7G. ps: 2627813 и 1872416 java-процесса в предыдущей строке — количество страниц, каждая страница — 4К.
Можно обнаружить, что использование памяти контейнера прекращается, потому что оно превышает системную память.
Используйте mat для анализа конкретных проблем с утечкой памяти.
Так как я не владею матовым инструментом, посмотрев карту распределения, итого всего 103,6Мб.Я думал, что с памятью в куче проблем нет, поэтому подумал о переполнении памяти вне кучи. Я проверял использование ThreadLocal в коде один за другим, и объекты вовремя очищались, проверял количество онлайн-потоков, явных проблем не обнаружено.
Перепечатайте статью о переполнении памяти вне кучи, вызванном слишком большим количеством потоков:Слишком много потоков вызывает переполнение памяти вне кучи
Продолжайте использовать мат-анализ, используйте функцию Leak Suspects и обнаружите, что в памяти находится большое количество объектов TrueTypeFont.
Просто подумал, что в этом приложении есть функция использования шрифтов для рисования картинок и отправки картинок. Поэтому я проверил состояние запроса OOM в то время и обнаружил, что действительно было большое количество запросов на рисование, и обнаружил, что более 600 рисунков были отрисованы одновременно в определенном запросе.
Проблема воспроизводится
Затем я смоделировал запрос в тестовой среде компании, и действительно, использование памяти выросло с более чем 60 до более чем 80.
Вернувшись назад и проверив код рисунка, я обнаружил, что проблема с обработкой шрифтов действительно есть.
Логика этого метода заключается в том, чтобы загрузить файл шрифта на сервер, с помощью кисти нарисовать QR-код, а затем сохранить его во временную директорию сервера.
Мы не очень хорошо поработали с загрузкой шрифтов здесь, так что каждый раз, когда приходит задача рисования, файл шрифта будет загружаться, а в памяти будет создаваться объект шрифта, а размер файла шрифта на нашем сервер составляет около 16 МБ, что эквивалентно каждому. Необходимо загрузить 16 МБ памяти, чтобы рисовать изображение за раз.
Проанализируйте причины
Поскольку в то время я не был знаком с матом, мне все еще было интересно, манипулирует ли Font пространством вне кучи. Итак, я готов протестировать дополнительное пространство кучи.
Устранение возможности переполнения пространства вне кучи
Конфигурация нашего сервера - память 8G, а jvm настроен как-Xmx4428m
-Xms4428m
-Xmn2767m,
Если пространство вне кучи не ограничено, оно будет похоже на пространство JVM. В настоящее время мы ограничиваем размер пространства вне кучи, например, указываем, что пространство вне кучи составляет всего 100 МБ. -XX:MaxDirectMemorySize=100m
.
Если Font использует пространство вне кучи, то пространство вне кучи вскоре достигнет 100 МБ, и будет выполняться полная сборка мусора, блокирующая все запросы, Stop The World. В это время, пока полный сборщик мусора очищается вовремя, последующие запросы на блокировку будут продолжать поступать, продолжать достигать 100M и продолжать полный сборщик мусора. Таким образом, использование памяти никогда не достигнет 8G, и не будет ситуации, когда система будет убита.
Однако во время теста было обнаружено, что использование памяти все еще растет, и в конце концов его убили.Так что позже я могу только снова подозревать, что это переполнение памяти в куче. Используя ту же стратегию, установите память кучи на 1G (100M не может быть применена), обнаружил, что память не продолжает увеличиваться, и проверил журнал gc, и выполнял полный GC, Из этого можно примерно видно, что использование памяти внутри кучи.
Из этого видно, что в пиковый период поступило большое количество запросов на отрисовку, в результате чего в память было загружено большое количество крупных объектов, что в итоге привело к превышению памяти jvm над системной памятью, а контейнер был убит системой.
Решать проблему
Измените шрифт на одноэлементный режим, в памяти существует только одна копия.
Попробовал еще раз в тестовой среде компании, и использование памяти не изменилось. После того, как релиз вышел в сеть, проблема больше не появлялась в сети, и проблема на время прекратилась.
Суммировать
-
Для онлайн-ошибок сайт должен быть защищен в первую очередь.
- Будьте особенно осторожны с операциями с большими объектами.
- Общие инструменты необходимо освоить, иначе будет потрачено много ненужного времени. При использовании мата для анализа задач вас больше должны волновать пропорции объекта, а не его размер. Если вы лучше знакомы с инструментами, вы можете сохранить работу по проверке пространства за пределами кучи позже.
- Если есть тревога, нужно вовремя ее прочитать, благо в этот раз зависла только одна машина, и большого влияния на онлайн это не оказывает.
последующие вопросы
Последующее расследование показало, что когда количество запросов было небольшим, после увеличения памяти не было OOM, но память не снижалась, и возникло подозрение на утечку памяти. Поиск TrueTypeFont с использованием гистограммы мата
Посмотрите еще раз на его корневой узел рециркуляции.
Отфильтруйте слабые ссылки и другие ссылки, которые не влияют на повторное использование.
Выяснилось, что в основном таких классов немного, класс Disposer мы видим чаще всего. Проверил роль Disposer в интернете.
В мате я отфильтровал слабые ссылки, а остальные обнаружили, что есть FontStrikeDisposer, который является сильной ссылкой на TrueTypeFont. Но эти цифры относительно небольшие, всего 8, что не должно работать. На этом цепочка прерывается, и я просматриваю исходный код TrueTypeFont, чтобы посмотреть, смогу ли я что-нибудь найти.