Докер по пределу ЦП AWS JVM - PullRequest
0 голосов
/ 04 июня 2019

Я запускаю наше весеннее загрузочное приложение в Docker-контейнере в сервисе AWS Fargate, поэтому, как только загрузка ЦП превышает 100%, контейнер останавливается Docker OOM-killer с ошибкой

Причина: OutOfMemoryError: Контейнер уничтожен из-за использования памяти

По метрикам мы видим, что процессор становится более 100%. Кажется, после некоторого времени профилирования мы обнаружили, что процессор потребляет код, но у меня вопрос: как процессор может быть больше 100%?

Можно ли сказать, что JVM использует только 100%?

Я помню, у нас была похожая проблема с потреблением памяти. Я прочитал много статей о cgroups, и было найдено решение указать

-XX: + UnlockExperimentalVMOptions -XX: + UseCGroupMemoryLimitForHeap

Таким образом, при запуске Docker с параметром -m = 512 размер кучи будет равен 1/4 размера mac. Размер кучи также можно настроить с помощью опции

-XX: MaxRAMFraction = 2

, который выделит 1/2 памяти докера для кучи. Должен ли я использовать что-то подобное для процессора? Я прочитал статью https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits,, но она говорит, что

Начиная с Java SE 8u131 и в JDK 9, JVM поддерживает Docker Относительно ограничений Docker CPU. Это означает, что если -XX: ParalllelGCThreads или -XX: CICompilerCount не указаны в качестве параметров командной строки, JVM будет применять ограничение ЦП Docker в качестве параметра количество процессоров, которые JVM видит в системе. Затем JVM отрегулирует количество потоков GC и потоков компилятора JIT, как это было бы как будто он работает на голой железной системе с установленным количеством процессоров в качестве предела CPU докера.

Команда Docker используется для запуска

docker run -d .... -e JAVA_OPTS='-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+PrintFlagsFinal -XshowSettings:vm' -m=512 -c=256 ...

Используется Java-версия

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

Дополнительная информация о приложении во время запуска

VM settings:
    Max. Heap Size (Estimated): 123.75M
    Ergonomics Machine Class: client
    Using VM: OpenJDK 64-Bit Server VM

ParallelGCThreads                         = 0   
CICompilerCount                          := 2
CICompilerCountPerCPU                     = true

1 Ответ

0 голосов
/ 14 июня 2019

Я нашел ответ на свой вопрос.Поведение для определения количества используемых процессоров было исправлено в https://bugs.openjdk.java.net/browse/JDK-8146115

Количество процессоров


Используйте комбинацию number_of_cpus () и cpu_sets () для того, чтобыопределите, сколько процессоров доступно для процесса, и соответствующим образом настройте JVM os :: active_processor_count.Number_of_cpus () будет рассчитываться на основе cpu_quota () и cpu_period () по следующей формуле: number_of_cpus () = cpu_quota () / cpu_period ().Если cpu_shares был настроен для контейнера, number_of_cpus () будет рассчитываться на основе cpu_shares () / 1024.1024 - это стандартная и стандартная единица для расчета относительного использования ЦП в облачном программном обеспечении для управления контейнерами.

Также добавьте новый флаг VM (-XX: ActiveProcessorCount = xx), который позволяет переопределять количество процессоров.Этот флаг будет соблюдаться, даже если UseContainerSupport не включен.

Поэтому в AWS вы обычно настраиваете cpu_shares на уровне определения задачи.До исправления jvm это вычислялось неправильно.

В версии java8 <191: cpu_shares () / 1024 = 256/1024 = был идентифицирован как 2 </p>

После миграции на версию java8> 191: cpu_shares () / 1024 = 256/1024 = был идентифицирован как 1

Код для проверки

val version = System.getProperty("java.version")
val runtime = Runtime.getRuntime()
val processors = runtime.availableProcessors()
logger.info("========================== JVM Info ==========================")
logger.info("Java version is: {}", version)
logger.info("Available processors: {}", processors)

Пример вывода

"Java version is: 1.8.0_212"
"Available processors: 1"

Надеюсь, это кому-нибудь поможет,поскольку я нигде не могу найти ответ (средство отслеживания проблем, поддержка AWS и т. д.)

...