Почему я получаю OOM с Docker? - PullRequest
0 голосов
/ 18 мая 2019

У меня есть Java-приложение, упакованное в Docker и размещенное на Amazon ECS.

Основные технологии:

  • SpringBoot 2
  • Java 8

Каждые 1-2 дня приложение аварийно завершает работу и снова просыпается, восстанавливаясь сервисом Amazon.

Под насекомым Docker я обнаружил причину:

"OOMKilled": true,

Я подключил привод к CloudWatch и обнаружил странное поведение с графиком потребления памяти:

Memory consumption

Эти синие пики - это моменты, когда приложение зависало.

Я читал, что в Java 8 есть проблемы с правильным чтением максимального объема памяти для хоста, но:

1) Docker запускается с флагами, которые должны решить проблему

ENTRYPOINT exec java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -Xms300M -XX:PermSize100M -Djava.security.egd=file:/dev/./urandom -jar /app.jar

2) В любом случае, у виртуальной машины есть 4 Гб оперативной памяти, поэтому максимальный пик ~ 1,3 Гб не должен убивать приложение.

3) Не было значительной нагрузки на сервер в моменты пиков

1 Ответ

1 голос
/ 18 мая 2019

-XX: PermSize100M

Не применимо для Java 8.

-XX: MaxRAMFraction = 1

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

Вместо этого следует выполнить одно из следующих действий:

  • использовать MaxRAMFraction=2 вместо 1
  • вручную установите Xmx на что-то меньшее, чем доступная память
  • Обновите до java> = 11 и используйте MaxRAMPercentage для более тонкой настройки
  • включите подкачку, чтобы допустить переполнение дополнительной памятина диск

Также см. "Является ли -XX: MaxRAMFraction = 1 безопасным для производства в загрязненной среде?" для получения дополнительной информации о более новых версиях Java.

...