Итак, у нас есть приложение среднего размера, основанное на JVM, и через неделю или две оно регулярно убивается OOM докером.Я прочитал все, что я мог найти о потреблении памяти Java 8 в контейнерах, экспериментальном флаге cgroup
, MaxRAM, управлении размером без кучи, оптимизации GC и так далее.Но в нашем случае нет способа заставить JVM выдать свое собственное исключение OOM.Это всегда докер, который убивает его с помощью кода 137.
Например, когда вы отдаете 2000M
памяти в контейнер и устанавливаете кучу на 80%
этого:
-XX:MaxRAM=1600M -XX:MaxRAMFraction=2
, что означает, что куча вырастет до 800M, в результате все равно будет OOM-kill docker.Мы начали с -Xmx
между 800M
и 1600M
- тот же результат.
При управлении размером без кучи (при условии, что максимум 100 потоков):
-XX:MaxRAM=1050M -XX:MaxRAMFraction=1 -Xss1M -XX:ReservedCodeCacheSize=128M -XX:MaxDirectMemorySize=64M -XX:CompressedClassSpaceSize=128M -XX:MaxMetaspaceSize=128M
и при достижении (100 * Xss) + 128M + 64M + 128M + 128M = 548M
для всей части незаполненной части требований к памяти JVM мы берем 2000M
памяти контейнера за вычетом 20%
минус 548M
некуча, дающая нам -XX:MaxRAM=1050M
, и все же мы убиты OOM.
Не уверен, имеет ли это значение, но мы запускаем кластер DC / OS, и это марафон, сообщающий об убийствах из-за OOM.Но я понимаю, что сообщается о поведении базового механизма докера.