Является ли -XX: MaxRAMFraction = 1 безопасным для производства в изолированной среде?
Java 8/9 предоставила поддержку для -XX:+UseCGroupMemoryLimitForHeap
(с -XX:+UnlockExperimentalVMOptions
). Это устанавливает -XX:MaxRAM
для ограничения памяти группы. По умолчанию JVM выделяет примерно 25% максимальной ОЗУ, потому что -XX:MaxRAMFraction
умолчанию -XX:MaxRAMFraction
4.
Пример:
MaxRAM = 1g
MaxRAMFraction = 4
JVM is allowed to allocate: MaxRAM / MaxRAMFraction = 1g / 4 = 256m
Использование только 25% квоты кажется пустой для развертывания, которое (как правило) состоит из одного процесса JVM. Итак, теперь люди устанавливают -XX:MaxRAMFraction=1
, поэтому JVM теоретически разрешено использовать 100% MaxRAM.
Для примера 1g это часто приводит к размерам кучи около 900 м. Это кажется немного большим - нет свободного места для JVM или других вещей, таких как удаленные оболочки или задачи вне процесса.
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
так же эта конфигурация (-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
) считается безопасным для prod или даже лучшей практики? Или мне еще нужно выбрать -Xmx
, -Xms
, -Xss
и так далее?
Ответы
Ответ 1
Мы провели простое тестирование, которое показало, что установка -XX:MaxRAM=$QUOTA
и -XX:MaxRAMFraction=1
приводит к гибели контейнеров под нагрузкой. JVM выделяет более 900 миллионов кучи, что слишком много. -XX:MaxRAMFraction=2
кажется безопасным (ish).
Имейте в виду, что вы можете оставить запас для других процессов, таких как получение отладочной оболочки (docker exec
) или диагностика в контейнере.
Изменение: мы написали то, что мы узнали подробно в статье. Денежные кавычки:
TL'DR: управление памятью Java и ее настройка все еще сложны. Хотя JVM может считывать ограничения памяти cgroup и соответствующим образом адаптировать использование памяти, начиная с Java 9/8u131, это не золотая пуля. Вам нужно знать, что делает -XX:+UseCGroupMemoryLimitForHeap
, и вам нужно точно настроить некоторые параметры для каждого развертывания. В противном случае вы рискуете потратить ресурсы и деньги или убить свои контейнеры в самый неподходящий момент. -XX:MaxRAMFraction=1
особенно опасно. Java 10+ приносит много улучшений, но все еще нуждается в ручной настройке. Чтобы быть в безопасности, загрузите тест своих вещей.
а также
Наиболее элегантным решением является обновление до Java 10+. Java 10 устарела -XX:+UseCGroupMemoryLimitForHeap
(11) и вводит -XX:+UseContainerSupport
(12), который заменяет его. Он также вводит -XX:MaxRAMPercentage
(13), который принимает значение от 0 до 100. Это позволяет детально контролировать количество оперативной памяти, которую JVM может выделить. Поскольку +UseContainerSupport
включен по умолчанию, все должно работать "из коробки".
Ответ 2
В недавнем oracle-jdk-8 (8u191) представлены следующие параметры, позволяющие пользователям контейнеров Docker получить более точный контроль над объемом системной памяти, которая будет использоваться для кучи Java:
-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage
Три новые опции JVM были добавлены, чтобы позволить пользователям контейнера Docker получить более детальный контроль над объемом системной памяти, которая будет использоваться для Java Heap:
-XX: InitialRAMPercentage -XX: MaxRAMPercentage -XX: MinRAMPercentage Эти параметры заменяют устаревшие формы дроби (-XX: InitialRAMFraction, -XX: MaxRAMFraction и -XX: MinRAMFraction).
См. Https://www.oracle.com/technetwork/java/javase/8u191-relnotes-5032181.html.