spring-cloud-gateway2.0 内存泄露问题排查

  1. Gateway2.0基本介绍
    1. 使用reactor-netty作为网络模型。
    2. 全程为reactor 编程方式。
  2. 问题报错信息

   

  1. 问题现象
    1. 服务上线不久隔断时间就会无法访问,假死。
      1. 初期解决方案:定时重启服务。
        1. 原因:业务需求压力过大,无精力深入排查该问题。且问题发生不严重。
  2. 内存快照

   

   

  1.  
  1. 问题复现
    1. 拿到代码,构建一个docker镜像,部署测试。
      1. 设置 JVM最大内存为 256M
    2. Jmeter 压测
  2. 复现结果
    1. 压测1.5个小时后,开始报错。 报错内容于 线上运行时异常一致。

   

  1. 问题分析
    1. 内存快照分析
      1. 明明已经使用到内存溢出了,但是内存快照才33M大小。
      2. 出现最多的为循环嵌套对象finalizer。
      3. 参考:
        1. 网络资料排查过程中,可以通过内存快照对象直接定位到哪里使用的这个对象,直接定位到问题点。
      4. 实际情况:
        1. 无限循环嵌套。无法定位到到底是哪里使用的这个对象。
    2. 代码检查
      1. 发现的问题
        1. 使用了rides
        2. 在网关中提供了API接口
        3. 在引入gateway的同时还引入了zuul
        4. 同时还引入了 spring-boot-starter-web
    3. 深入排查
      1. 在压测中第一个报错的信息为
      2. 问题分析
        1. ResourceLeakDetector 为 netty 内存泄漏检测机制 ,默认为1%的抽样检查。
        2. 可以得到信息,netty 发送了内存泄露。
        3. 但是,这只能说明是内存泄露了,但是定位不到泄露点。
      3. 问题开始变为定位泄露点。
      4. 继续压测后得到线上错误日志
        1. [网关异常处理]请求路径:/stars/cust/api/communicate/queryRecordByItemCode,异常信息:io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct
        2. memory (used: 1895825415, max: 1908932608)
        3. 当前日志同样定位不到泄露点
        4. 代码位置
        5. 把堆栈信息吃掉了!吃掉了!
      5. 信息分析
        1. 得到已知信息
          1. 确认为netty 内存泄露照成的服务不可用
          2. netty 使用的内存为 堆外内存(直接内存)
      6. 继续调整压测
        1. 修改 jvm 启动参数 -XX:MaxDirectMemorySize=50M 缩减固定堆外内存大小
      7. 新的问题出现
        1. 加入堆栈异常输入后 日志报错为 netty rides 内存溢出!
        2. 并未保留日志与截图,就不提供了。
      8. 新问题排查
        1. 百度得到的信息是 spring-boot-starter-data-redis 组件使用了netty为通讯模块,排查掉netty后 ,使用jedis,不在报错。
      9. 继续压测
        1. 问题并未解决,还是netty内存溢出。
        2. 逐行百度相关信息
          1. 网络上有报相同错误的,但是都说Netty 特定版本有问题,我们使用相关依赖并非该版本
      10. 继续压测
        1. 调整内容
          1. 只压测 getaway本身,将相关依赖全部去掉,排查是否 为getaway本身问题。
        2. 压测结果
          1. Getaway 本身无问题,不报错。
      11. 信息分析
        1. 既然getaway 本身没有问题,必然是相关依赖出现了问题。照成了 响应结果没释放引起的内存溢出。
        2. 继续排查
          1. 发现矛盾点
            1. 在内存快照中, netty 与 tomcat相关对象都有被创建。
            2. 初步还以为引入的 spring-boot-starter-web 的tomcat 照成的问题。
      12. 继续压测
        1. 调整内容
          1. 排除 spring-boot-starter-web 的 tomcat 相关依赖引用
      13. 结果
        1. 不在报错!!!!

   

   

   

  1. 排查结果
    1. getaway 2.0 使用的是 netty 做为容器, 在引入 spring-boot-starter-web 组件的时候会引入 tomcat 容器。
    2. tomcat 内对象也被创建了,在响应的时候,照成了netty 与 tomcat 类相关使用的问题。
    3. 从内存快照中其实也可以看到的,当时并未特别注意。

   

  1. 解决方案
    1. 排除 spring-boot-starter-web 的 tomcat 相关依赖引用

   

   

  1. 问题延时
    1. 打异常的时候,能打堆栈信息,就一定要打出来!要不真的不好排除定位问题!
    2. 在不是特别了解的情况下,那就劲量做到模块单一原则。让getaway 只做网关自己的事情!

   

   

   

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章