Java и Docker. Часть 1
Сейчас Java всё чаще используется в контейнерах, обычно в Docker. Формально в Docker можно положить любую версию Java, и это даже как-то будет работать. Однако когда вышла Java 8, про работу в Docker ещё никто и не думал.
Это приводит к весьма неприятным последствиям. Например, приложение не учитывает ограничение на процессоры и может создавать пулы с большим количеством потоков или не видит ограничение по памяти и неожиданно закрывается Docker-ом при превышении лимита.
Работа в контейнере начала улучшаться, начиная c Java 9 (есть и обратные порты в Java 8), в релизе Java 10 был добавлен новый параметр
Давайте посмотрим, как это работает. По умолчанию
Runtime.getRuntime().availableProcessors().
Соберём образ и запустим контейнер такой командой:
docker run --memory=100m --cpus 2 java-docker
Вводим ограничение для контейнера: память 100 Мб и 2 процессора. В контейнере запускается такая команда:
CMD java -XX:+PrintFlagsFinal -version | grep MaxHeapSize
Получаем результат:
size_t MaxHeapSize = 52428800
Это примерно 52 Мб, т. е. примерно половина лимита контейнера.Теперь посмотрим на доступные процессоры:
CMDjava -jartestJavaAppl.jar
Возвращает:
Runtime.getRuntime().availableProcessors(): 2
Видим, что Java-приложение учитывает в своей работе лимиты, заданные контейнером. Давайте повторим эксперимент, но на этот раз отключим режим
CMD java -XX:-UseContainerSupport -XX:+PrintFlagsFinal -version | grep MaxHeapSize
Получаем:
size_tMaxHeapSize = 8415870976
Java не видит ограничение в 100 Мб и пытается использовать память «на всю котлету». А теперь смотрим, что происходит с процессором:
CMD java -XX:-UseContainerSupport -jar testJavaAppl.jar
Получаем:
Runtime.getRuntime().availableProcessors(): 12
И по процессорам Java пытается использовать все системные ресурсы, игнорируя ограничения Docker-а. Очевидно, что для корректной работы Java-приложения в Docker-е желательно использовать версию Java 10 или новее.
В следующей заметке затронем другие аспекты работы Java-приложения в контейнере. А более подробно посмотрим на это дело на открытом вебинаре «Java и Docker».