spring-cloud-gateway2.0 內存泄露問題排查


  1. Gateway2.0基本介紹
    1. 使用reactor-netty作為網絡模型。
    2. 全程為reactor 編程方式。
  2. 問題報錯信息

 

  1. 問題現象
    1. 服務上線不久隔斷時間就會無法訪問,假死。
      1. 初期解決方案:定時重啟服務。
        1. 原因:業務需求壓力過大,無精力深入排查該問題。且問題發生不嚴重。
  2. 內存快照

     

     

  3.  
  4. 問題復現
    1. 拿到代碼,構建一個docker鏡像,部署測試。
      1. 設置 JVM最大內存為 256M
    2. Jmeter 壓測
  5. 復現結果
    1. 壓測1.5個小時后,開始報錯。 報錯內容於 線上運行時異常一致。

   

問題分析

 

  1. 內存快照分析
    1. 明明已經使用到內存溢出了,但是內存快照才33M大小。
    2. 出現最多的為循環嵌套對象finalizer。
    3. 參考:
      1. 網絡資料排查過程中,可以通過內存快照對象直接定位到哪里使用的這個對象,直接定位到問題點。
    4. 實際情況:
      1. 無限循環嵌套。無法定位到到底是哪里使用的這個對象。
  2. 代碼檢查
    1. 發現的問題
      1. 使用了redis
      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. 不在報錯!!!!

   

   

   

  • 排查結果
    • getaway 2.0 使用的是 netty 做為容器, 在引入 spring-boot-starter-web 組件的時候會引入 tomcat 容器。
    • tomcat 內對象也被創建了,在響應的時候,照成了netty 與 tomcat 類相關使用的問題。
    • 從內存快照中其實也可以看到的,當時並未特別注意。

       

  • 解決方案
    • 排除 spring-boot-starter-web 的 tomcat 相關依賴引用

       

       

  • 問題延時
    • 打異常的時候,能打堆棧信息,就一定要打出來!要不真的不好排除定位問題!
    • 在不是特別了解的情況下,那就勁量做到模塊單一原則。讓getaway 只做網關自己的事情!

       

   

   

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM