jvm 开启容器感知 cgroup 的配置(终极 jvm 配置)
一、JVM感知cgroup
基于Docker等容器方式运行Java应用时,容器的资源管理使用了操作系统 cgroup 机制,但是JVM无法感知cgroup。
也就是说在没有UseContainerSupport参数支持的JDK版本中,JVM是无法感知容器环境存在,对容器资源的限制比如内存或者cpu等都无法生效。在这种情况下,如果JVM申请的内存大于容器的内存,容器就会把当前进程kill掉,所以必须要让JVM感知到能使用的最大内存,这样可以及时进行GC。
UseContainerSupport作用
为了支持JVM感知cgroup的内存限制,在JDK1.8的8u91版本之后引入了默认开启的UseContainerSupport参数。
另外,由于容器内存管理方式的出现,仅仅通过Xmx、Xms参数来配置JVM中堆内存的方式无法很好地适配通过容器内存调整来管理JVM内存大小。
所以JVM还提供了 MaxRAMPercentage,InitialRAMPercentage,MinRAMPercentage 三个参数,这三个参数用途是指定JVM堆内存的相对容器内存的占比。通过控制容器内存大小就能实现动态控制JVM内存大小,例如容器分配4G,如果MaxRAMPercentage设置为75.0则JVM最大堆内存为4*0.75即3G,如果要提升JVM堆内存大小只需要调整容器内存即可。
一般来说MaxRAMPercentage MinRAMPercentage参数可以配置为75.0或80.0。
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=75.0
-XX:InitialRAMPercentage=75.0
-XX:MinRAMPercentage=75.0
参数说明:
JVM参数之MaxDirectMemorySize VM将用于直接字节缓冲区的堆内存量限制为最大堆大小的大约85%
Xmn 的大小为最大堆内存的 1/3
Xmx, Xmn 设置一样大
首先要调整的,就是各个分区的大小,不过这也要分垃圾回收器,我们仅看一下一些全局的参数。
-XX:+UseG1GC 首先,要指定JVM使用的垃圾回收器。尽量不要靠默认值去保证,要显式的指定一个,这里指定G1垃圾回收器,如:-XX:+UseG1GC -Xmx32g -XX:MaxGCPauseMillis=200;
-Xmx 设置堆的最大值,一般为操作系统的2/3大小。
-Xms 设置堆的初始值,一般设置成和Xmx一样的大小来避免动态扩容。
-Xmn 年轻代大小,默认新生代占堆大小的1/3。高并发快消亡场景可适当加大这个区域。对半,或者更多,都是可以的。但是在G1下,就不用再设置这个值了,它会自动调整。
-XX:MaxMetaspaceSize 限制元空间的大小,一般256M足够。这一般和初始大小**-XX:MetaspaceSize**设置成一样的。
-XX:MaxDirectMemorySize 设置直接内存的最大值,限制通过DirectByteBuffer申请的内存。
-XX:ReservedCodeCacheSize 设置JIT编译后的代码存放区大小,如果观察到这个值有限制,可以适当调大,一般够用。
-Xss 设置栈的大小,默认为1M,已经足够用了。
-XX:+UseContainerSupport允许JVM 从主机读取cgroup限制,例如可用的CPU和RAM,并进行相应的配置。这样当容器超过内存限制时,会抛出OOM异常,而不是杀死容器。该特性在Java 8u191 +,10及更高版本上可用。
二、终极配置
dockerfile文件配置
# java version 1.8.0_251
FROM jdk8 # 示例
ENV enyType = ${envTypeVar}
...
# 使用G1垃圾回收器,UseContainerSupport 在JDK1.8的8u91版本之后可以使用,当前jdk版本为 java version 1.8.0_251 符合要求;
ENV JAVA_OPTS="-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Xmx4096m -Xms4096m -Xmn1360m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=256M -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=75.0 -XX:MinRAMPercentage=75.0 "
EXPOSE 9880
WORKDIR /code/
ENTRYPOINT java ${JAVA_OPTS} -Dspring.property.path=/code -Dspring.profiles.active=${envType} -jar /cloud/app.jar
#下面这样写法不行,他只是拼接不会识别变量
#ENTRYPOINT ["java","${JAVA_OPTS}","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]
相关文章:
k8s 的 jvm 内存泄露排查
容器环境 JVM 内存配置最佳实践
JVM调优参数之UseContainerSupport
G1垃圾收集器详解
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)