1.现象:
线上跑跑定时任务的机器每天下午4点cpu会飙升到98%持续一段时间后容器会挂掉
2.问题分析
2.1从容器中根据jvm中配置的dump相关参数,找到堆转储文件路径中的hprof文件
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/temp/logs/dump 当有oom异常发生时,会记录堆转储文件到指定路径下
2.2下载hprof文件到本地
2.3导入jprofiler分析
首先查看类的分布情况,发现byte[]数组是占比最多的:类分布.png
然后查看大对象的分布情况:
大对象分布式.png
然后查看第一个大对象的调用链,发现可能跟数据库查询结果有关。
大对象引用链.png
进一步分析ArrayList对象的元素,发现跟cdn_fee_task表有关系,进一步定位到相应的sql语句,发现sql进行了全表查询,单次查询300万数据到内存。由于该任务是扫描实时计费的失败任务,每天下午4点触发,且随着交易量的增加,最终导致问题发生。
大对象.png
相关表和字段定位sql.png
3为什么会全表查询
service层查询条件中有status字段,但是dao层的sql中并没有将该字段作为where查询条件。并且之前实时计费最小粒度是天,数据量没有特别大,后来增加了小时计费数据量飙升
4.解决方式
更改sql使where生效,并添加索引字段。