频繁Full GC问题排查定位
先上结论:长时间运行MetricsClientHttpRequestInterceptor.servoMonitorCache.timerCache积累过多且不回收,导致频繁fullGc
起因:运维的同事说,你这个服务运行时间长了,内存不回收啊,内存一直往上加,我们半月就得重启一次,要不就返回503了,我心想不可能啊,java自带内存回收,后来一看系统监控果然,内存大趋势随着时间线性增长,很稳定,放大之后发现,内存是有回收的,只是每次的最低点都在提高,我第一反应是,对象到老年代了,一直在养老,钉子户越来越多导致的,那就铲除钉子户吧。
jstat -gcutil [pid] 1000 查看gc执行频率,确实一直在Full GC ,而且还收不干净。
jmap -F -dump:format=b,file=heapDump [pid] 先保留现场,不能让服务一直不可用,留好快照,让运维的同事先重启解决下。
用eclipse mat 工具打开dump文件,文件太大,3.13g,需要修改mat启动参数,如图:
主要是这两行-Xmx4096m,-Xms1024m
点击Leak Suspects,查找内存泄漏
发现内存泄漏的class,
- org.springframework.cloud.netflix.metrics.MetricsClientHttpRequestInterceptor
- org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache(servoMonitorCache)
java.util.HashMap(timerCache)
回到源码,查找对应class,发现
Intercepts RestTemplate requests and records metrics about execution time and results.原来是为了统计执行时间和返回结果的,那就关掉吧。
在MetricsInterceptorConfiguration中
1
@ConditionalOnProperty(value = "spring.cloud.netflix.metrics.enabled", havingValue = "true", matchIfMissing = true)
默认是true,需要在自己的配置文件中添加spring.cloud.netflix.metrics.enabled=false
发版本,上线,观察内存监控,很平稳。