zoukankan      html  css  js  c++  java
  • 引用中间件导致的OOM问题调查

    一次使用中间件引发的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中注入了这个类,上到预发环境,解决问题;

    总结

    • 中间件这样实现的原因是为了在从properties解析存储到动态配置解析转换时减少开发,这里缺少一个case将多例的引用不做缓存,直接请求;
    • 在springBoot 使用多例时注意,看是否有会被其他实例长期引用而无法释放,导致OOM;
    • 在新功能上线之前,dump预发环境的内存,看是否存在某个类实例异常多的情况,使用jprofiler 分析一下引用关系,看是否出现了内存泄漏;
    I am chris, and what about you?
  • 相关阅读:
    eclipse maven项目 热部署
    二十三. Django ModelForm组件
    二十二 .Django生命周期
    二十二 .Django form上传+Ajax+FormData上传+Form组件上传+序列化+ifram伪造Ajax
    二十一. Django----ajax全部
    二十. Django ajax--请求数据 和模态对话框
    二十. Django分页 和自定义分页
    十九. Django-Cookie的CBV和FBV的用户验证装饰器
    十八 .Django session应用
    十七 .Django cookie应用
  • 原文地址:https://www.cnblogs.com/arax/p/14857596.html
Copyright © 2011-2022 走看看