背景
一次项目巡检发现某个项目的函数执行TP99的波动很大:
看这个图感觉很离谱,随即排查问题原因,看到JVM的监控如下:
发现程序一直在执行fullGC,我们知道fullGC的成本是非常大的,这肯定是导致应用卡顿的原因。
尝试解决
我去看了机器的监控,发现服务是部署在8G内存的容器里面的,实际占用内存只有7%都不到。
通过这里我们知道,实际机器的内存还是有很大的富余的,那肯定是哪里限制了jvm去使用更多的内存了。
找到我们应用的启动脚本,发现下面一行配置:
#========================================================================================== # JVM Configuration # -Xmx256m:设置JVM最大可用内存为256m,根据项目实际情况而定,建议最小和最大设置成一样。 # -Xms256m:设置JVM初始内存。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存 # -Xmn512m:设置年轻代大小为512m。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。 # 持久代一般固定大小为64m,所以增大年轻代,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8 # -XX:MetaspaceSize=64m:存储class的内存大小,该值越大触发Metaspace GC的时机就越晚 # -XX:MaxMetaspaceSize=320m:限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序 # -XX:-OmitStackTraceInFastThrow:解决重复异常不打印堆栈信息问题 #========================================================================================== JAVA_OPT="-server -Xms256m -Xmx256m -Xmn512m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m"
好吧,查到问题所在了,这里配置jvm的内存限制,限制的太小了,改成 `JAVA_OPT=”-server –Xms3550m –Xmx3550m –Xmn2g -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m”` 重新发布
各项指标都恢复正常了!
后续
可能有的同学要问了,这个jvm限制参数有啥用? 为啥要配置他?我可以不配置吗?
查阅相关资料发现,如果你不配置这个限制的话,他默认会使用系统可用内存的1/4来作为最大内存。
比如你系统内存32G,那么默认你不配置的话,你的应用只能用到8G。
如果是多应用共享,你是否真的可以使用8G ? 如果是独占服务器,剩下的24G内存是否浪费?
还有一种情况是容器环境,虚拟机可能128G内存,然而只给你容器分配了8G内存,如果这时候你不指定的话,JVM可能获取到的就是128G内存的1/4,显然他会导致你超额使用的情况。
所以,最好还是指定下你的应用JVM的内存配置在一个合理的值。
参考资料:
https://blog.csdn.net/wc1695040842/article/details/109160209