一次线上Full GC 的排查过程
一、常用命令
内存分析常用命令:
// 打印每个class的实例数目,内存占用,类全名信息.live子参数加上后,只统计活的对象数量. 此时会触发FullGC
jmap -histo:live <pid> > filename | head -10
// dump 内存
jmap -dump:live,format=b,file=/opt/logs/dump.hprof <pid>
// 查看堆栈使用情况
jmap -head pid
// 垃圾回收统计概述
jstat -gc <pid> <time>
// 垃圾回收统计概述,使用空间占总空间的百分比
jstat -gcutil <pid> <time>
// 用于生成java虚拟机当前时刻的线程快照
jstack <pid>
二、问题描述
我们系统中存在一个定时任务,每次执行任务时都会触发full gc,稳定复现。是一个报表计算的任务,会把原始表的数据经过加工整理汇总到指标表,涉及数据大批量插入的情况
三、排查过程
排查思路是:发生fullgc时保留现场,dump内存,然后利用Jprofiler去分析。为了能采集到理想的内存数据,通过查看监控,发现内存占用量接近触发full gc的阈值时dump内存。
- 选择机器:
set-xr-xx-service-rental02,禁用,跑定时任务触发fullgc。
- dump内存命令:
代码块
Java
map -dump:live,format=b,file=dump_after_fullgc_3.hprof 58988
- 查看监控,每次发生fullgc时dump一次内存
文件名称 | 大小 |
---|---|
dump_before.hprof | 542M |
dump_after1.hprof | 423M |
dump_after2.hprof | 455M |
dump_after_fullgc_3.hprof | 1.5G |
dump_after_fullgc_oldgen70p.hprof | 1.2G |
dump_after_fullgc_time3k.hprof | 1.9G |
dump_after_fullgc_4.hprof | 1.6G |
主要分析内存占用比较大的三个文件即可
- 内存文件下载到本地
- 分析:
Biggest Objects:
架构组提供的加解密包,sql解析缓存,LRUCache占了842MB的内存,明显不正常。缓存的内容是sql是批量插入
再看classes:
内存占用排名前三的是SQLVariantRefExpr、byte[]、char[],逐个点击incoming references分析:
SQLVariantRefExpr:
都是druid数据源的东西,每个实例内存占用并不大,总占用量才340M,问题好像不在这里。
byte[]:
mysql-jdbc元数据缓存、thrift序列化的一些数据,内存占用并不大
char[]:
这里才是问题的真正所在
全是批量插入sql语句的解析缓存,根据前面的Biggest OBjects分析,这部分数据来自架构组加解密包中的sql解析缓存,为什么会有这么大的数据量呢?
分析代码:
SqlParser中维护了一个size为1000的LRUCache,采用LinkedHashMap实现的LRU算法,每次会把解析后的sql结构缓存起来。当size>1000时会采用LRU算法淘汰。
通过Jprofiler分析,cache中元素个数刚好1000个,最大的key为10MB。
四、结论
通过分析这段代码发现,问题出在我们批量插入的数据量太大,且每次插入行数数不固定,sql解析的结果基本每次都不同,很难命中缓存。导致缓存不断增大,并且批量插入数据量非常大,导致存入的key很大,内存占用急剧上升。老年代内存占用过大时触发了full gc。分析到这里,解决办法就相对清晰了。
跟架构组的人沟通后决定:
1.业务侧针对批量插入数据的场景,先限制每次插入的行数,固定50行。这样缓存中最多会插入50个元素,其他的都会命中缓存。
2.架构组针对大批量数据插入的情况做优化。每次插入超过50不走缓存,实时解析。50以内的走缓存,命中概率也很高;针对大批量插入的情况,更换接入方式,业务方直接调用rpc接口去加解密。目前是通过mybatis 拦截器改写sql实现的。不太适合大批量数据插入的情况。
五、修复
批量插入数据改为批量插入。利用guava的Lists强大的功能,很容易实现分页。
上线后执行定时任务,发现fullgc次数明显下降,gc时间也变短了很多,达到了预期的效果。
标题:一次线上Full GC 的排查过程
作者:guobing
地址:http://www.guobingwei.tech/articles/2020/08/13/1597274443518.html