Openjdk 8合理使用容器的内存资源

前言

将Java应用容器化虽然更好地解决了可移植性问题,但也存在着一些不友好的情况,比如低版本的JDK(低于Java 8u131)并不能识别 CGroup资源限制。这将导致JVM读取的是宿主机的全部CPU和内存,一但容器使用资源超过限制则会被docker杀死。

在 kubernetes 中,我们会显示在 yaml 文件中配置CPU、内存请求和限制,我们希望容器中的JVM进程能够自动识别到 CGroup 资源限制,获取到正确的内存和CPU信息从而自行动态调整。

JVM 参数配置

以下操作皆在一台 4C 16G 服务器上进行。

01 版本低于 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)


02 8u131 及以上版本

从 8u131 版本开始支持 UseCGroupMemoryLimit

ForHeap 和 MaxRAMFraction 这两个选项,用 CGroupMemory 的大小作为 JVM heap size,MAXRAMFraction 是用来控制实际可用的内存数量的,比如设置为 1 的话就是 CGroupMemoryLimit 的全部,设置为 2 的话一半,3 的话就是 1/3,以此类推

未配置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)
03 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 大小

$ 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 使用的内存比率

$ 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/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值