在Openjdk 8 中如何合理使用容器 memory 资源
前言
将 Java 应用容器化虽然更好地解决了可移植性问题,但也存在着一些不友好的情况,比如低版本的JDK(低于Java 8u131)并不能识别 CGroup 资源限制。这将导致JVM读取的是宿主机的全部CPU和内存,一但容器使用资源超过限制则会被 docker 杀死。
在 kubernetes 中,我们会显示在 yaml 文件中配置CPU、内存请求和限制,我们希望容器中的JVM进程能够自动识别到 CGroup 资源限制,获取到正确的内存和CPU信息从而自行动态调整。
JVM 参数配置
以下操作皆在一台 4C 16G 服务器上进行。
版本低于 8u131
JDK 版本低于 8u131 版本的 JVM 不会自动识别到 CGroup 资源限制,需要手动设置初始堆大小以及最大堆大小,否则会按照宿主机的全部内存设置默认值:
- 配置最大堆大小
-Xmx
,默认值:内存的1/4 -
配置初始堆大小
-Xms
,默认值:内存的1/64
未配置JVM参数
可以看到 Max. Heap Size (Estimated): 3.48G
,未能正确识别 CGroup 资源限制
$ docker run --rm -m 2GB openjdk:8u121-alpine java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 3.48G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_121" OpenJDK Runtime Environment (IcedTea 3.3.0) (Alpine 8.121.13-r0) OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
配置JVM参数
配置 -Xmx
和 -Xms
后即可达到我们想要的结果
$ docker run --rm -m 2GB openjdk:8u121-alpine java -XshowSettings:vm -Xmx2000m -Xms2000m -version VM settings: Min. Heap Size: 1.95G Max. Heap Size: 1.95G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_121" OpenJDK Runtime Environment (IcedTea 3.3.0) (Alpine 8.121.13-r0) OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
8u131 及以上版本
从 8u131 版本开始支持 UseCGroupMemoryLimitForHeap
和 MaxRAMFraction
这两个选项,用 CGroupMemory
的大小作为 JVM heap size,MAXRAMFraction
是用来控制实际可用的内存数量的,比如设置为 1 的话就是 CGroupMemoryLimit
的全部,设置为 2 的话一半,3 的话就是 1/3,以此类推
|MaxRAMFraction取值|堆占比|容器内存=1G|容器内存=2G|容器内存=4G|容器内存=8G|容器内存=16G| |:—-:|:—-|:—-:|:—-|:—-:|:—-|:—-:|:—-|:—-:|:—-|:—-:|:—-|:—-:|:—-| |1|≈90%|910.50M|1.78G|3.56G|7.11G|14.22G| |2|≈50%|455.50M|910.50M|1.78G|3.56G|7.11G| |3|≈33%|304.00M|608.00M|1.19G|2.37G|4.74G| |4|≈25%|228.00M|455.50M|910.50M|1.78G|3.56G|
未配置JVM参数
可以看到 Max. Heap Size (Estimated): 3.48G
,未能正确识别 CGroup 资源限制
$ docker run --rm -m 2GB openjdk:8u131-alpine java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 3.48G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_131" OpenJDK Runtime Environment (IcedTea 3.4.0) (Alpine 8.131.11-r2) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)
配置JVM参数
配置 -XX:+UnlockExperimentalVMOptions
、-XX:+UseCGroupMemoryLimitForHeap
和 -XX:MaxRAMFraction=1
后即可达到我们想要的结果
$ docker run --rm -m 2GB openjdk:8u131-alpine java -XshowSettings:vm -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -version VM settings: Max. Heap Size (Estimated): 1.78G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_131" OpenJDK Runtime Environment (IcedTea 3.4.0) (Alpine 8.131.11-r2) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)
8u191 及以上版本
从 8u191 开始引入了 java10+ 上的 UseContainerSupport
选项,而且是默认启用的,不用设置。同时 UseCGroupMemoryLimitForHeap
这个就弃用了,不建议继续使用,同时还可以通过 -XX:InitialRAMPercentage
、-XX:MaxRAMPercentage
、-XX:MinRAMPercentage
这些参数更加细腻的控制 JVM 使用的内存比率。比如一些 Java 程序在运行时会调用外部进程、申请 Native Memory 等,所以即使是在容器中运行 Java 程序,也得预留一些内存给系统的。所以 -XX:MaxRAMPercentage
不能配置得太大。
未配置JVM参数
可以看到未添加任何 JVM 参数即可正确识别到 CGroup 资源限制
$ docker run --rm -m 2GB openjdk:8u191-alpine java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 455.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_191" OpenJDK Runtime Environment (IcedTea 3.10.0) (Alpine 8.191.12-r0) OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
配置JVM参数
- 使用
-XX:MaxRAMFraction
参数调整Max. Heap Size
大小 ```console $ docker run –rm -m 2GB openjdk:8u191-alpine java -XX:MaxRAMFraction=1 -XshowSettings:vm -version
VM settings: Max. Heap Size (Estimated): 1.78G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM
openjdk version “1.8.0_191” OpenJDK Runtime Environment (IcedTea 3.10.0) (Alpine 8.191.12-r0) OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
* 使用 `-XX:InitialRAMPercentage`、`-XX:MaxRAMPercentage`、`-XX:MinRAMPercentage` 参数更加细腻的控制 JVM 使用的内存比率 ```console $ docker run --rm -m 2GB openjdk:8u191-alpine java -XX:InitialRAMPercentage=40.0 -XX:MaxRAMPercentage=90.0 -XX:MinRAMPercentage=50.0 -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 1.60G Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_191" OpenJDK Runtime Environment (IcedTea 3.10.0) (Alpine 8.191.12-r0) OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
参考资料
- http://www.51gjie.com/java/551.html
- https://zhuanlan.zhihu.com/p/140849800
- https://my.oschina.net/neverforget/blog/4779579
- https://sevenyu.top/2019/04/01/java-resources-limit.html
- https://qingmu.io/2018/12/17/How-to-securely-limit-JVM-resources-in-a-container/
本文由猪齿鱼技术团队原创,转载请注明出处:猪齿鱼官网
关于猪齿鱼
猪齿鱼Choerodon全场景效能平台,提供体系化方法论和协作、测试、DevOps及容器工具,帮助企业拉通需求、设计、开发、部署、测试和运营流程,一站式提高管理效率和质量。从团队协同到DevOps工具链、从平台工具到体系化方法论,猪齿鱼全面满足协同管理与工程效率需求,贯穿端到端全流程,助力团队效能更快更强更稳定。戳此处试用猪齿鱼

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
从网络通信的演进过程彻底搞懂Redis高性能通信的原理(全网最详细,建议收藏)
我们一直说Redis的性能很快,那为什么快?Redis为了达到性能最大化,做了哪些方面的优化呢? 在深度解析Redis的数据结构 这篇文章中,其实从数据结构上分析了Redis性能高的一方面原因。 在目前的k-v数据库的技术选型中,Redis几乎是首选的用来实现高性能缓存的方案,它的性能有多快呢? 根据官方的基准测试数据,一台普通硬件配置的Linux机器上运行单个Redis实例,处理简单命令(O(n)或者O(logn)),QPS可以达到8W,如果使用pipeline批处理功能,QPS最高可以达到10W。 Redis 为什么那么快 Redis的高性能主要依赖于几个方面。 C语言实现,C语言在一定程度上还是比Java语言性能要高一些,因为C语言不需要经过JVM进行翻译。 纯内存I/O,内存I/O比磁盘I/O性能更快 I/O多路复用,基于epoll的I/O多路复用技术,实现高吞吐网络I/O 单线程模型,单线程无法利用到多核CPU,但是在Redis中,性能瓶颈并不是在计算上,而是在I/O能力,所以单线程能够满足高并发的要求。 从另一个层面来说,单线程可以避免多线程的频繁上下文切换以及同步锁机制带...
- 下一篇
2021年10月国产数据库排行榜:达梦反超OceanBase夺榜眼,TDSQL实现“四连增”,数据生态加速建设
2021年10月国产数据库排行榜已在墨天轮发布,本月共有150家数据库参与排名。我们可以用“半江瑟瑟半江红”来形容10月份数据库分数涨跌情况。除去分数没有变化的数据库,分数上涨和下跌的数据库数量大约各占一半。笔者对大事件进行梳理的过程中发现,很多数据库厂商没有对公司重大事件进行多种渠道传播,这影响了其流行度的评分。 首先来看一下排行榜 TOP3 阵容。PingCAP的TiDB本月分数上涨12.30,稳坐榜首。TiDB本月分数增长离不开其开源生态方面取得的成果。9月份,PingCAP与苏黎世联邦理工学院高级软件技术实验室签署合作协议,将以开源分布式数据库TiDB为载体,对数据库事务测试体系进行共同的探索。此外,TiDB社区首批通过可信开源社区评估,获评OSCAR尖峰开源项目及开源社区。社区力量仍是TiDB稳守第一位的重要支撑因素。 达梦分数强势上涨45.30,是本月分数增加最多的数据库,总分达到了478.33,以大分差超过OceanBase,实现了笔者上个月的预判,名次上升一名,夺得榜眼之位。在笔者看来,达梦本月表现抢眼的原因有以下几点:第一,密集参加重大行业会议。9月份,达梦亮相中国国...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- Hadoop3单机部署,实现最简伪集群
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker安装Oracle12C,快速搭建Oracle学习环境