首页 > 解决方案 > Springboot App在docker上消耗太多内存

问题描述

尝试使用docker部署容器化的 springboot 应用程序。这是我的Dockerfile

ROM openjdk:8
ADD app-1.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xmx64m", "-Xss256k", "-jar", "ecalio-landing.jar"]

运行这样的容器

sudo docker run -d -m256m --restart=always server.tomcat.max-threads=5 --name=ecalio-landing

部署后我使用apache 基准测试后端以及使用此命令可以达到多少请求:

ab -n 20000 -c 10 http://www.ecalio.com/

基本上,试图知道后端是否可以一次达到 20000 个请求 10 ,因为我已将容器内存消耗限制256mb

容器从220mb开始,达到245mb 左右的水平,即使重新运行相同的ab 命令也不会走得更远

但是,当我尝试使用浏览器访问后端时,每次刷新浏览器都会消耗 0.1mb,显然一旦达到 256mb内存消耗,容器就会崩溃。

怎么会发生这种事

我不希望我的容器消耗太多内存,它基本上是一个简单的应用程序,它仅使用带有1 个实体模型的jpa,并且每次使用简单的控制器@Controller )调用/ url时只执行 1 个检索请求和返回使用thymeleaf呈现的单个 html 页面

我在我的应用程序中使用了 Java VisualVM(在没有 docker 容器的情况下在我的机器上本地启动),我可以清楚地看到我的应用程序没有任何内存泄漏,堆内存不会超过 68mb 并且已使用GC总是清除堆...

分析内存

标签: spring-bootdockertomcatdeploymentmemory-leaks

解决方案


经过这么多的斗争,我找到了解决方案,这太荒谬了......

当这两个选项没有传递给 JVM 时,它假设容器与主机共享相同数量的资源,即使 -m 参数被传递给容器的创建命令......

-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap

这意味着如果我使用 -m300m 创建一个容器来指定我的容器不应分配超过 300mb,jvm 仍然会认为容器有权使用 2gb 内存(其中 2gb 是我机器的物理内存)

使用这些选项,我能够让我的应用程序在 256mb 容器上运行......当我知道有一次,我的容器消耗高达 800mb 时真是太神奇了......

来源:

官方openjdk的docker镜像

有趣的文章

我的新 Dockerfile:

FROM openjdk:8
ADD app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-server", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-jar", "app.jar"]

-server有助于让 JVM 知道应用程序将在服务器环境中执行,这将导致一些变化,包括用于服务器环境的 GC 专用算法以及可能在官方文档中找到的一些其他行为。

请注意,内存限制不需要 Xmx 或 Xss 或任何其他选项,因为 JVM 将自行修复所有内容(下面的文章中有更多详细信息)

另一件要知道的是,这个配置是在 OpenJDK 11 中自动完成的。


推荐阅读