生产上一次频繁gc的故障分析
事情是这样的,公司的微服务监控系统显示我所在项目的一个服务频繁掉线。接到这个消息后。
首先,我觉得可能是服务器oom内存溢出了。就去查看服务状态,发现服务heap正常,表现出来的效果是正常的,就像没有掉线过一样。
然后,直接去找运维,去生产上的容器中,查看服务器状态。
1,通过 jps 查到服务进程
jps
2,通过如下命令查看服务内存状态
jstat -gc pid
效果如下
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
135168.0 131584.0 63200.0 0.0 257536.0 57943.6 5718016.0 2111288.4 124952.0 116668.8 15152.0 13708.0 912880 47662.680 1028 17732.733 65395.413
累计fgc达到1000多次。ygc达到90多万次。特么的,简直被震惊了。特么,一次fgc时间达到10多秒。这下微服务监控显示频繁掉线的原因就呼之欲出了。本服务fgc次数过多,时间过长,导致本服务不能发给nacos心跳,让nacos以为本服务已经掉线,然后就触发频繁掉线报警。
3,gc过多的原因
通过如下命令,查看服务内存信息
jmap -heap pid
效果如下
Attaching to process ID 9, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
using thread-local object allocation.
Parallel GC with 103 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 6392119296 (6096.0MB)
NewSize = 536870912 (512.0MB)
MaxNewSize = 536870912 (512.0MB)
OldSize = 5855248384 (5584.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.tools.jmap.JMap.runTool(JMap.java:201)
at sun.tools.jmap.JMap.main(JMap.java:130)
Caused by: java.lang.RuntimeException: unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
at sun.jvm.hotspot.tools.HeapSummary.run(HeapSummary.java:144)
at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:49)
... 6 more
可以看到最大heap为6g,而新生代只有512m。频繁gc的原因也很明显了,新生代过少,导致频繁ygc,而服务数据量又大,就导致很多数据到了老年代。老年代满了,又fgc,又因为老年代过大,导致fyc时间变的很长。
4,解决方式
改启动参数 如下
java -jar -Xms6048M -Xmx6048M -Xmn3588M -XX:-UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M -XX:SurvivorRatio=8 *.jar