Spring Boot App 在 docker 上消耗过多内存
Springboot App consumes too much memory on 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 的 内存消耗就崩溃了。
怎么会发生这种事 ?
我不希望我的容器消耗太多内存,它基本上是一个简单的应用程序,它使用 jpa 和 1 entity model only, and perform only 1 retrieve request called each time / url 使用简单的 controller (@Controller) 和 returns 用 thymeleaf
呈现的 单个 html 页面
我在我的应用程序中使用了 Java VisualVM(在我的机器上本地启动,没有 docker 容器),我可以清楚地看到我的应用程序没有任何内存泄漏,堆内存不会超过 68mb,并且使用过的堆总是被 GC 清除 ...
经过这么多的努力,我找到了解决办法,这太荒谬了...
当这 2 个选项未传递给 JVM 时,它假设容器与主机共享相同数量的资源,即使 -m 参数传递给容器的创建命令...
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
这意味着如果我使用 -m300m 创建一个容器来指定我的容器不应该分配超过 300mb,jvm 仍然会认为容器有权使用 2gb 的内存(其中 2gb 是我机器的物理内存内存)
使用这些选项,我能够让我的应用程序在 256mb 的容器上运行...当我知道有一次我的容器消耗了 800mb 时,真是太神奇了...
来源:
Official openjdk's docker image
我的新 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 中自动完成。
正在尝试使用 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 的 内存消耗就崩溃了。
怎么会发生这种事 ?
我不希望我的容器消耗太多内存,它基本上是一个简单的应用程序,它使用 jpa 和 1 entity model only, and perform only 1 retrieve request called each time / url 使用简单的 controller (@Controller) 和 returns 用 thymeleaf
呈现的 单个 html 页面我在我的应用程序中使用了 Java VisualVM(在我的机器上本地启动,没有 docker 容器),我可以清楚地看到我的应用程序没有任何内存泄漏,堆内存不会超过 68mb,并且使用过的堆总是被 GC 清除 ...
经过这么多的努力,我找到了解决办法,这太荒谬了...
当这 2 个选项未传递给 JVM 时,它假设容器与主机共享相同数量的资源,即使 -m 参数传递给容器的创建命令...
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
这意味着如果我使用 -m300m 创建一个容器来指定我的容器不应该分配超过 300mb,jvm 仍然会认为容器有权使用 2gb 的内存(其中 2gb 是我机器的物理内存内存)
使用这些选项,我能够让我的应用程序在 256mb 的容器上运行...当我知道有一次我的容器消耗了 800mb 时,真是太神奇了...
来源:
Official openjdk's docker image
我的新 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 中自动完成。