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 只做網關自己的事情!

   

   

   

   

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