Безопасно ли использовать -XX:MaxRAMFraction=1 в продакшене в контейнеризованной среде?
Описание проблемы:
В Java 8/9 была добавлена поддержка параметра -XX:+UseCGroupMemoryLimitForHeap
(в сочетании с -XX:+UnlockExperimentalVMOptions
). Этот параметр устанавливает -XX:MaxRAM
в значение лимита памяти cgroup. По умолчанию JVM выделяет примерно 25% от максимального объема RAM, так как по умолчанию -XX:MaxRAMFraction
равен 4.
Пример:
MaxRAM = 1g
MaxRAMFraction = 4
JVM может выделять: MaxRAM / MaxRAMFraction = 1g / 4 = 256m
Использование лишь 25% от выделенной квоты кажется расточительным для развертывания, которое (обычно) состоит из одного процесса JVM. Поэтому многие пользователи устанавливают параметр -XX:MaxRAMFraction=1
, чтобы теоретически разрешить JVM использовать 100% MaxRAM.
В случае примера с 1g это часто приводит к размеру кучи примерно 900m. Это вызывает некоторые сомнения — остается недостаточно свободного места для самой JVM и для других процессов, таких как удаленные оболочки или внешние задачи.
Возникает вопрос: является ли такая конфигурация (-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
) безопасной для использования в продакшене или это считается наилучшей практикой? Или все же стоит вручную подбирать -Xmx
, -Xms
, -Xss
и другие параметры?
1 ответ(ов)
Недавно была выпущена версия oracle-jdk-8 (8u191), которая предлагает новые параметры для пользователей Docker-контейнеров, позволяя более точно контролировать объем системной памяти, который будет использоваться для Java Heap:
-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage
Эти три новых параметра JVM добавлены, чтобы предоставить пользователям Docker более тонкий контроль над использованием памяти. Они заменяют устаревшие варианты с дробными значениями (-XX:InitialRAMFraction, -XX:MaxRAMFraction и -XX:MinRAMFraction).
Дополнительную информацию можно найти по ссылке: https://www.oracle.com/technetwork/java/javase/8u191-relnotes-5032181.html
Что такое параметры -Xms и -Xmx при запуске JVM?
Как определить, запущен ли код в 64-разрядной или 32-разрядной JVM (изнутри программы)?
Регистрация нескольких хранилищ ключей в JVM
Почему компилятор Java 11 использует invokevirtual для вызова приватных методов?
"Как задать количество потоков/ЦП для Java VM?"