首页 > 其他 > 详细

引用中间件导致的OOM问题调查

时间:2021-06-07 12:12:15      阅读:25      评论:0      收藏:0      [点我收藏+]

一次使用中间件引发的OOM调查

描述问题

在上一次上线完成后,线上的系统在运行几天后就会收到FullGC频繁的告警,而且每台服务都会告警,万能的重启可以解决问题,但不是根本办法,肯定是上一期的代码出现了内存泄漏,在预发环境上,由于操作次数较少,这个问题很难暴露。于是dump 线上的内存,用JProfiler对hprof 文件进行了分析

分析及解决过程

分析文件

使用jprofiler打开 dump文件后,在大对象分析中,发现有个http 请求的封装类有居然有130141个实例,着实把我吓了一跳。
技术分享图片

这个实例在代码中的确是prototype的,但是在引用他的地方,使用spring的注入方式,不会存在依赖无法释放的问题。在AlphaDataRemoteData 类中目前只存在两个注入的变量
技术分享图片

技术分享图片

查看Jprofiler实例的引用关系:
技术分享图片

技术分享图片

猜想及验证

可以看到一个FieldValueProcessor 引用了AlphaDataRemoteData这个类,同时也引用了 多例类中注入的@Value;spring的变量注入在populateBean中就会完成,不会生成单独的类,处理注入的value,在看FieldValueProcessor类的包名,猜想应该是引用上次上线引入的中间件导致的问题,引入的中间件的功能是可以在线修改配置变量,不用重启服务就可以生效。该中间件支持spring原生的@Value注入。查看FieldValueProcessor的源码:
技术分享图片

技术分享图片

确实引用类bean,而最终的GCRoot中是单例的,他内部存储着一个ConcurrentHashMap来缓存这些需要监听的key和key所说的bean,这是一条强依赖的引用链,无法释放;这个类主要负责用户手动点击后,请求其他系统的,5天10万的数量级在数量上也是匹配的,也说明了为什么ConfigruatorManager为什么占用18M内存的原因
技术分享图片

解决问题

目前无法移除这个中间件,窜在两种改法,

  • 将AlphaDataRemoteData注入的property 移动到一个单一的类中,AlphaDataRemoteData 注入这个类;
  • 那么就将AlphaDataRemoteData修改为单例的,将其内部的成员变量改为外部传入的方式;
    本着修改最小的原则,我们将注入的实例移动到一个单独的配置类中,并在AlphaDataRemoteData中注入了这个类,上到预发环境,解决问题;

总结

  • 在springBoot 使用多例时注意,看是否有会被其他实例长期引用而无法释放,导致OOM;
  • 在新功能上线之前,dump预发环境的内存,看是否存在某个类实例异常多的情况,使用jprofiler 分析一下引用关系,看是否出现了内存泄漏;

引用中间件导致的OOM问题调查

原文:https://www.cnblogs.com/arax/p/14857596.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!