Docker容器中设置jvm参数
set jvm in docker
Contents
背景
- java默认是通过/proc/meminfo来取服务器内存数据的,而docker容器中/proc/meminfo文件记录的是宿主机的内存参数,jvm堆最大值默认是服务器的1/4,这样就可能会导致docker容器的限制内存最大值可能小于jvm堆内存上限。
- 现象就是在jvm触发fullGC或者majorGC之前堆内存就已经快达到容器最大内存限制,导致容器将java进程杀死。
- oracle在JDK 1.8u131开始对Docker容器进行支持,以解决上述问题,并且在JDK1.8u191版本进行了完善,因此升级JDK版本到1.8u191之后的版本即可解决问题(备注:不仅仅是内存,CPU同样如此,比如:Java应用容器化后GC的问题以及解决方案)
- 参考资料:oracle官网 Java Improvements for Docker Containers 章节,可能需要梯子
解决方案
1、设置-Xmx最大内存
- 缺点就是每次更改容器最大限制内存都要更改一下对应-Xmx参数的值,显然这种是不合适的。
2、通过设置堆占内存比例的方式设置堆的最大内存值
Docker是通过cgroup来实现最大内存设置的,添加识别cgroup配置的jvm参数即可读取到docker容器的内存最大值
JDK 8u131+、JDK 9版本可以设置如下参数指定堆最大内存如下所示,其中MaxRamFraction默认值是4,堆内存的利用率比较低,可以适当调高该占比
1 2 3-XX:+UnlockExperimentalVMOptions #(开启实验性参数) -XX:+UseCGroupMemoryLimitForHeap # (指定JVM从主机读取cgroup限制) -XX:MaxRAMFraction=int #(服务器内存/jvm最大内存,默认是4,只能设置为整数,一般都是2)不使用MaxRamFraction设置最大内存占比,而是将容器最大内存限制设置到环境变量中,在容器内通过环境变量读取到容器最大内存限制后通过-Xmx来设置堆最大内存为读取到的环境变量的80%,这样的好处是可以更灵活的配置堆的内存参数
JDK 8u191+、JDK 10及以上版本可以使用如下参数来动态指定jvm堆内存最大值(推荐)
1 2-XX:+UseContainerSupport #(使用容器内存) -XX:MaxRAMPercentage =75.0 #(使用容器内存百分比,表示jvm占容器内存75%)