spring-boot - 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总是清除堆...
解决方案
经过这么多的斗争,我找到了解决方案,这太荒谬了......
当这两个选项没有传递给 JVM 时,它假设容器与主机共享相同数量的资源,即使 -m 参数被传递给容器的创建命令......
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
这意味着如果我使用 -m300m 创建一个容器来指定我的容器不应分配超过 300mb,jvm 仍然会认为容器有权使用 2gb 内存(其中 2gb 是我机器的物理内存)
使用这些选项,我能够让我的应用程序在 256mb 容器上运行......当我知道有一次,我的容器消耗高达 800mb 时真是太神奇了......
来源:
我的新 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 中自动完成的。
推荐阅读
- node.js - 使用 NoSQL 数据库计算用户数
- r - R中的列表可以很大吗?R 不会让我创建这个列表
- c# - 如何确定在 C# ASP.NET CORE MVC 5.0 中选择了哪个单选按钮
- python - 当给定一个类的相同实例的列表时,deepcopy 的行为如何
- python - 数据框中列值之间的成对交集操作
- mysql - MySQL Query 与另一个表的状态检查
- spring-boot - Spring JPA 投影 - 在嵌套对象列表中选择特定列
- python - 如何在每个循环获取新输出的 for 循环中附加一个数组?
- java - 如何使用 iText 5 将 PDF 文件嵌入到现有文件中
- mediawiki - MediaWiki 不同名称空间的不同站点标题