一次线上Full GC 的排查过程

  |   0 评论   |   0 浏览

一、常用命令

内存分析常用命令:

// 打印每个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,稳定复现。是一个报表计算的任务,会把原始表的数据经过加工整理汇总到指标表,涉及数据大批量插入的情况

image.png

三、排查过程

排查思路是:发生fullgc时保留现场,dump内存,然后利用Jprofiler去分析。为了能采集到理想的内存数据,通过查看监控,发现内存占用量接近触发full gc的阈值时dump内存。

  1. 选择机器:

set-xr-xx-service-rental02,禁用,跑定时任务触发fullgc。

  1. dump内存命令:

代码块

Java

map -dump:live,format=b,file=dump_after_fullgc_3.hprof 58988
  1. 查看监控,每次发生fullgc时dump一次内存
文件名称大小
dump_before.hprof542M
dump_after1.hprof423M
dump_after2.hprof455M
dump_after_fullgc_3.hprof1.5G
dump_after_fullgc_oldgen70p.hprof1.2G
dump_after_fullgc_time3k.hprof1.9G
dump_after_fullgc_4.hprof1.6G

主要分析内存占用比较大的三个文件即可

  1. 内存文件下载到本地
  2. 分析:

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 的排查过程
作者:guobingwei
地址:http://guobingwei.tech/articles/2020/08/13/1597274443518.html