一次线上OOM 的定位
问题背景
收到业务监控报警
[告警名称:jvm.fullgc.count]
[告警指标:jvm.fullgc.count]
最近5个点值:[N/A,N/A,N/A,N/A,1606]
触发规则:
[最新5个点求和 > 5 ]
数据时间:2021-03-31 07:53:00
告警时间:2021-03-31 07:54:21
持续时长:just now
查看监控数据
![fullgc.count (分钟级别) fullgc.count (分钟级别)](./images/1617543631869.png)
fullgc.count (分钟级别)
登录机器发现,服务已挂掉。
问题定位
查看 JVM 参数配置,并没有配置 HeapDumpOnOutOfMemoryError 参数。查看异常日志,发现报错信息如下
![OOM OOM](./images/1617546846521.png)
OOM
可见,是元空间内存溢出。查看 JVM 关于元空间的参数配置
-XX:MetaspaceSize=250m -XX:MaxMetaspaceSize=250m
一般而言,我们调整上述参数,增加元空间的大小即可。但仍存在一个疑问,服务已经运行了很久了,为什么之前没有问题,而现在突然出现问题?
-
查看服务的发布记录,发现 3.30 号有一位小同学对此服务进行了发布。咨询了一下发布的功能和逻辑、查看其代码及涉及的数据量后,发现其新功能每隔几分钟就会获取大量的数据并处理,此时会占用大量的内存。在处理的过程中,会动态产生类。
-
观察元空间的占用统计情况,发现即使在没有执行新功能的时候,元空间的占用也达到了 90% 以上。
解决方案
主要通过以下三个手段:
- 增加元空间的大小至 350M
- 将单次执行任务的数据量减少。主要手段为分页获取数据,虽然对元空间的影响不大,但可以减少单次对新生代的内存占用
- 增加对元空间占用大小的监控,当元空间占用大小超过 80% 时,发送提醒通知,当达到 90% 时,发送报警通知