记一次JVM生产OOM及后续调优

2020年03月18日,开年第一个生产事故发送在我的项目组o(╥﹏╥)o

事故发生

在下午2点40时,收到了第一个客户投诉,紧接着收到了第二个、第三个。
并且不断的有各业务系统表示自己的系统出现了操作无响应的现象,如此大范围的影响,推测大概率是网关的功能出现了问题。

事故定位

立马上日志平台搜索Nginx处的请求日志,果然在Nginx上发现了大量的499响应码日志,紧接着拿着top 1请求量的499接口来搜索安全网关的日志,发现了大量的:java.lang.OutOfMemoryError: GC overhead limit exceeded,由于怕过年期间生产不稳定,从年前开始,已经很长时间都没有发布了,所以排除了新增的代码BUG。

解决

那么就有可能是长时间运行慢慢堆积的对象导致的OOM,直接重启安全网关,重启后成功解决。

复盘

java.lang.OutOfMemoryError: GC overhead limit exceeded根据官方的解释是在多次gc后效果极差抛出的OOM。
怀疑可能存在内存泄漏,直接分析OOM后的dump文件。
在这里插入图片描述
从Dominator Tree图中排出占用内存最大的top n对象,挨个查看它的GC root:
在这里插入图片描述
再切换到Histogram,同样排出占用内存最大的top n对象,挨个查看GC root。

调优

分析后发现skywalking和spring产生了大量的Class对象,skywalking产生了大量的Endpoint对象,spring产生了大量的动态代理对象。并没有自身代码产生的内存泄漏对象。

  1. 适当的调大JVM堆大小
  2. 进一步调查Endpoint对象,是否可以控制过期时间。

事故的调查期间还发现了服务自启动以来只有过2次full gc,都是在启动初期由于Metaspace空间不足扩容导致的full gc,所以还需要调整Metaspace空间。

-XX:MetaspaceSize=128M

另外,我还调低了MaxTenuringThreshold,这个参数影响进入老年代的年龄阈值。
因为网关的对象都是请求级别的生命周期,分析gc日志可以知道young gc平均在30s执行一次,MaxTenuringThreshold的默认值是15,会导致部分长期存活对象需要将近8分钟的时间才能进入老年代,本来年轻代的空间就不大,再被这些长期存活对象一占用,会使得young gc更加频繁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值