Недостаточно памяти в приложении swisscom cloudfoundry springboot
У меня есть приложение SpringBoot, которое нуждается только в макс. 284 МБ памяти. Но я могу только запустить приложение с макс. 768 МБ памяти. Даже если я уменьшу память позже, я всегда получаю следующую ошибку:
[APP/PROC/WEB/0] ERR Cannot calculate JVM memory configuration: There is insufficient memory remaining for heap. Memory limit 384M is
less than allocated memory 672509K (-XX:ReservedCodeCacheSize=240M, -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=109309K, -Xss1M * 300 threads)
Я уже использую то же самое приложение в cf без этой проблемы. Что изменилось в cf? До 2 или 3 недель это все еще работало.
Заранее спасибо за быстрый ответ!
2 ответа
Я уже использую то же самое приложение в cf без этой проблемы. Что изменилось в cf? До 2 или 3 недель это все еще работало.
Вы должны быть обновлены до Java Build Pack v4. С JBP v3 вы могли загружать приложения с меньшим объемом памяти, но приложения, которые были загружены с этой версией buildpack и небольшими ограничениями памяти, также были очень подвержены сбоям. Причина этого заключается в том, что JBP v3 не учитывал все области памяти, используемые JVM, когда JBP выполнял свои вычисления, поэтому, хотя это и позволило бы вашему приложению запуститься, приложение все равно могло бы превысить свой предел памяти позже. Теперь JBP v4 вычисляет память более точно и учитывает все области памяти JVM.
В результате приложения JBP v4, работающие с объемом оперативной памяти менее 1 ГБ, могут увидеть следующую ошибку при подготовке, а приложения, работающие с 512 МБ или меньше, почти наверняка увидят эту ошибку при подготовке:
ERR Cannot calculate JVM memory configuration: There is insufficient memory remaining for XXXX
Тем не менее, Java-приложения, которые успешно работают на сцене, значительно менее подвержены сбоям.
Значит ли это, что вы не можете запустить приложение Java с объемом оперативной памяти менее 1 ГБ? Нет. Вы можете, но это потребует некоторой настройки. Вот список некоторых вещей, которые вы можете настроить, чтобы сэкономить память.
Число потоков. JBP предполагает, что ваше приложение будет работать с 250 потоками. Это довольно распространенное явление для веб-приложения, в котором будет около 50 для внутреннего содержимого Tomcat и 200 для обработки запросов. Вы можете уменьшить это значение, но вам нужно убедиться, что ваше приложение не превышает установленное количество потоков, иначе ваше приложение может аварийно завершить работу. Для вас это будет настройка конфигурации Tomcat с помощью Spring Boot.
Пример меньшего числа потоков для JBP:
cf set-env my-application JBP_CONFIG_OPEN_JDK_JRE '{ memory_calculator: { stack_threads: 50 } }'
Пример меньшего числа потоков в приложении Spring Boot.properties:
server.tomcat.max-threads=25
Примечание: это просто потоки обработки запросов. У Tomcat есть потоки, и ваше приложение может создавать потоки. Вы действительно должны посмотреть дамп потока или JVisualVM, чтобы увидеть, сколько потоков требуется вашему приложению (то есть измерять, не угадывать)
Размер стека потока (-Xss). Это значение передается в JVM, которая контролирует, сколько памяти требуется для каждого потока. По умолчанию это 1M, что очень высоко. В большинстве случаев вы можете безопасно снизить его до 160 КБ, что является минимально допустимым для Java 8. Если у вас есть 250 потоков и вы сделаете это изменение, вы сэкономите (1М * 250) - (160К - 250) = 211М ОЗУ,
Примечание. Если вы слишком сильно уменьшите размер стека потоков, в вашем приложении появятся исключения Stackru. Если это произойдет, сохраняйте спокойствие и повышайте значение до тех пор, пока они не исчезнут.
Уменьшите кэш зарезервированного кода. Это где JVM кеширует JIT-код. По умолчанию это 240M. Вы можете уменьшить это значение, но делайте это с осторожностью, поскольку это может абсолютно повлиять на производительность. Вы также можете увидеть ошибки во время выполнения, если это значение недостаточно велико.
Опять же, лучше измерить то, что требует ваше приложение, чем угадывать. Вы должны быть в состоянии измерить, используя NMT JVM.
Вы можете вручную настроить другие области памяти, используемые JVM, такие как Heap & Metaspace. С JBP v4 это так же просто, как установить переменную среды JAVA_OPTS с помощью
cf set-env
или в вашемmanifest.yml
файл. Очевидно, что если вы понижаете эти значения, вы должны быть осторожны, чтобы не опуститься слишком низко, и в этом случае вы получите OutOfMemoryErrors.Примечание. Если вы оставите один регион незаданным, например, кучу или метапространство, JBP умно вычислит его с учетом того, что осталось после ручной настройки.
Надеюсь, это поможет!
Я не эксперт по обработке памяти java-приложений в облачном литейном производстве, но из того, что я понял, нужно знать следующее:
- Приложения Java обычно развертываются через Java Buildpack. Если вы не определили версию в вашем manifest.yml, она займет ветку master. Поскольку основная ветвь постоянно меняется, я предполагаю, что параметры развертывания также могут измениться.
- Пакет Java Build использует калькулятор памяти Java Buildpack для оценки параметров памяти JVM, таких как
-Xmx
, Вы можете настроить эти параметры самостоятельно в своем manifest.yml, но это не рекомендуется, если вы хотите использовать функции масштабирования облачного литейного производства. - Итак, если вы определите, что вашему облачному приложению разрешено использовать память объемом 500 МБ, а калькулятор пакетов сборки оценивает больше, это может не сработать и привести к некоторым ошибкам.
Что вы можете сделать в своем манифесте, так это поиграться со всеми параметрами, упомянутыми в документах калькулятора памяти. Например, вы можете дать подсказку калькулятору, если вам нужно меньше потоков (например, memory_calculator: { stack_threads: 100}
)
Когда вы справляетесь с "жестким кодированием" некоторых параметров памяти: вот пример manifest.yml для моего приложения Spring Boot 2 / Java 9, которое я использую с ограничением 400 МБ. Это работает для меня, но, вероятно, не то, чтобы скопировать сразу. Это зависит от вашего приложения.
applications:
- name: demo-app
path: target/demo-app-1.0.0.jar
instances: 1
buildpack: https://github.com/cloudfoundry/java-buildpack.git
memory: 400m
env:
JAVA_OPTS: '-XX:MaxMetaspaceSize=80780K -Xss512k -Xmx200M -XX:ReservedCodeCacheSize=16M -XX:MaxDirectMemorySize=16M'
JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 9.+ } }'