遇到的问题现象:
GC格外的频繁 总之 咔咔GC
JVM的配置项
主要关注两个配置
-
-XX:+UseContainerSupport: 启用容器支持,允许JVM感知容器环境,并根据容器的资源限制来自动调整内存使用。
-
-XX:MaxRAMPercentage=80.0: 设置JVM最大可用内存为物理内存的80%。
从设置者的角度来看,是为了可以更好的配合 k8s的容器的大小,来适配JVM的大小。这设置Java8-191以上版本都是也可以支持的。
当然 JVM的堆大小的调整 通过 -Xmx -Xms 也是可以的,但是当我们K8S的容器调整后,jvm的是无法感知到容器的变化的,自然无法自适应的缩小,会导致在超过容器大小后 被kill掉。总之很不通用,无法根据容器的分配自适应,也无法感知容器大小,运维起来很麻烦。
最好的实践还是开启 +UseContainerSupport。增加这个配置的初发点也是为此着想。
但是这种配置为何导致了GC的频繁呢。
容器申请的7G,理应很“富裕啊”。
接着看了下 线上的heap 信息
(・◇・)? 我5.6G的堆你就给我 56MB的Old seize !为何如此小气的分配。
反观 配置 MaxRAMPercentage,有max 是不是会有min和 initial 的配置,难道是因为没设置的缘故么?
果然发现线上是有的
默认值 -XX:InitialRAMPercentage=1.562500
默认值 -XX:MinRAMPercentage=50.000000
InitialRAMPercentage, MinRAMPercentage, MaxRAMPercentage的区别
这篇文章说的很清楚 ,InitialRAMPercentagez作为jvm虚拟机启动的时候的大小,‘-XX: InitialRAMPercentage’用于计算 java 应用程序的初始堆大小。假设你正在配置-XX: InitialRAMPercentage = 25,并且总体物理内存(或容器内存)是1 GB,那么你的 java 应用程序的堆大小将是 ~ 250 MB (即1 GB 的25%)。
而 MaxRAMPercentage,MinRAMPercentage 只有在物理服务器(或容器)中的总可用内存大小小于250 MB (大约)时才用于计算 Java 堆大小。
结论:
使用姿势的不正确 ,InitialRAMPercentageme没设置 导致走了默认的 1.5的比例,导致jvm启动后 分配的实际jvm内存极小,导致系统频繁触发fullGC ,所以赶紧调整使用姿势 ,将MaxRAMPercentage 和 InitialRAMPercentagez设置一样即可,另外如果你的整个物理服务器(或容器)内存大小超过250 MB,那么你不必配置“-XX: MinRAMPercentage”,只需配置“-XX: MaxRAMPercentage”就足够了。大多数企业级 Java 应用程序的运行大小将超过250mb。
调整:
-XX:MaxRAMPercentage=85.0
-XX:InitialRAMPercentage =85.0
注:论坛有提 If -Xmx is set, MaxRAM is never used. 所以如果设置xmx 就不要用RAX了。
只有在没有传递‘-Xms’JVM 参数时,才会使用‘-XX: InitialRAMPercentage’来派生初始堆大小。如果传递了‘-Xms’JVM 参数,JVM 将忽略‘-XX: InitialRAMPercentage’。
Conclusion
Thus, in a nutshell:
a. To set the initial heap size for your application use ‘-XX:InitialRAMPercentage’
b. ‘-XX:InitialRAMPercentage’ will not take effect to determine the initial heap size if ‘-Xms’ is configured.
c. Both ‘-XX:MinRAMPercentage’ and ‘-XX:MaxRAMPercentage’ are used to set the application’s max heap size.
d. ‘-XX:MinRAMPercentage’ and ‘-XX:MaxRAMPercentage’ will not take effect to determine max heap size if ‘-Xmx’ is configured.
e. If your overall physical server (or container) memory size is more than 250MB, then you don’t have to configure ‘-XX:MinRAMPercentage’, it’s sufficient if you just configure ‘-XX:MaxRAMPercentage’. Most enterprise grade Java applications will be running with more than 250MB (unless you are building IoT or network device applications in Java).