1.现象
某业务方的网关服务上线2个月后,出现15分钟一次fullgc.
2.触发fullgc的可能原因
- System.gc()方法调用
代码里一般都禁用了,不可能。 ( X ) - 老年代空间不足
open-falcon上查指标 ,经核对,距离分配的空间还差很远就被回收了。 ( X ) - 永生代(Metaspace不足)
open-falcon上查指标,经核对,还未达到。 ( X ) - 堆中分配大对象
(所谓大对象,是指需要大量连续内存空间的java对象,例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full
GC。) =》 观察老年代的回收情况,跟这种情况很符合。(可能) - CMS GC时出现promotion failed和concurrent mode failure
jdk8 默认使用的-XX:+UseParallelGC (UseParallelGC 即 Parallel Scavenge + Parallel Old ) (X) - HandlePromotionFailure (X)
3.重现及验证猜想
分析代码中可能的大对象,猜测到是做请求指标统计的时候,参考hystrix的时间窗口,对请求进行统计,这个统计容器一直没释放。
所以开始批量压测进行重现,经过2天的持续访问,终于重现问题。然后导出堆内存结构,并对内存结构进行分析,确实是统计指标的容器(一个concurrentHashMap)占用了很大的空间,触发了fullgc.
TODO:后面补图
4.问题解决
4.1 通过定时清空该容器的方式来解决。
4.2 时间窗口的分片粒度太小,调大一点,可以节约空间,也不影响统计的准备性。
参考资料:
什么时候会触发fullgc