Проблемы с памятью при переходе на JDK 17: опыт команды Spring АйО

В процессе перехода с JDK 8 на JDK 17 команда Spring АйО столкнулась с серьезными проблемами, связанными с утечкой памяти. Миграция прошла успешно на этапе разработки и тестирования, но в продуктивной среде уже через 2-3 часа начались сбои.

  • Увеличение потребления памяти в 4 раза
  • Контейнеры начали перезапускаться из-за OOMKill
  • Количество потоков возросло с 400 до более 1600
  • Нативная память увеличилась с 800 MB до 3,6 GB

Причины проблем с памятью

Проблема заключалась в нескольких аспектах, усилившихся в контейнеризованной среде:

  1. Неверное определение CPU: JVM игнорировала лимиты CPU в cgroup, что приводило к созданию избыточного количества потоков.
  2. Фрагментация malloc-арен: Из-за увеличения количества потоков, glibc создавала слишком много malloc-арен, что увеличивало использование памяти.
  3. Накладные расходы G1GC: Переход на G1GC увеличил потребление нативной памяти.

Исправления и рекомендации

После тщательного анализа команда внедрила несколько исправлений:

Исправление Описание
Установка количества CPU -XX:ActiveProcessorCount=2
Ограничение malloc-арен export MALLOC_ARENA_MAX=2
Настройка или замена G1GC Использование ParallelGC или настройка G1GC

После этих изменений использование памяти стабилизировалось на уровне 65-70%. Команда подчеркнула важность мониторинга как нативной, так и heap-памяти, чтобы избежать подобных инцидентов в будущем.

Эти уроки подчеркивают, что миграция JVM требует тщательного планирования и анализа, что важно учитывать при обновлении до новых версий Java.

Понравилась статья? Поделиться с друзьями: