【Java】排障方法論

在這裏插入圖片描述

大神文章的總結。整理人: pierre


機器異常、代碼Bug、業務邏輯不當、開源組件使用姿勢不對等等都會造成我們的現網後臺服務不穩定,甚至是出現嚴重的服務掛掉的情況。當面對如此複雜的現網環境時,我們需要有一個清晰的問題排查思路,有章可循方能行之有度。總結一些問題排查的思路。

一、備份現場

  • 問題出現的前後幾分鐘往往比較關鍵
  • 要全:儘可能地把對問題分析有幫助的現場信息都保留備份
  • 要快:系統在異常情況下錯誤日誌的輸出會更加頻繁,可能覆蓋掉關鍵日誌

1、備份應用日誌

應用日誌是最佳切入問題的點:

  • 一般系統出現問題時都會有相應的異常日誌輸出
  • 能夠定位到具體的代碼片段,縮小問題排查範圍

2、記錄問題發生的時間

所有的信息都能通過時間這個維度刻畫

  • 問題發生時間點基礎資源是否有波動(網卡流量飆升、CPU利用率飆升等)
  • 是否存在變更操作,系統是否做過升級

3、備份GC日誌

  • JVM的垃圾回收線程優先級高於應用線程

    一旦出現頻繁FULL GC的情況,應用級別的線程基本處於掛起狀態,有時甚至連應用日誌也不會輸出。

  • 長時間的FULL GC就意味着系統無響應,對外表現出來的現象就是超時及不可用

  • 判斷是否需要進行JVM調優

4、監控基礎資源利用率曲線

  • 可視化的曲線
  • 峯值以及走勢
    過與前一天或者前一週相同時刻的曲線進行對比,爲解決問題提供一個良好的參照

5、獲取堆棧快照信息

jstack ${pid}> ${pid}.jstack
  • 調用棧上下文
  • 線程的狀態(是否阻塞、僵死、死鎖)信息

6、Dump內存信息

jmap -dump:live,format=b,file=${pid}.hdump.bin ${pid}

可以分析:

  • 內存泄漏
  • 對象回收不掉導致垃圾回收頻繁

二、分析問題

計算機的四個核心組成部分:CPU、內存、網絡、磁盤

1、CPU

綜合CPU利用率高

  • 非CPU密集型應用CPU突然飆高一定是系統存在異常情況
  • CPU密集型應用則需要考量是否有優化的空間
排查思路:
  • top -Hp $pid列出當前進程對應的線程佔用CPU情況
  • 把佔用CPU資源最高的線程ID(十進制)轉換成十六進制的值
  • 備份好的堆棧信息pid.jstack找到該十六進制值所對應的線程調用棧

一般當前調用棧所執行的代碼就是導致CPU高的根源。當然方法調用可能存在系統調用的情況,這部分信息可能在堆棧中體現不出來。這種情況還需要通過系統性能分析工具perf、strace等進一步統計分析,找出消耗CPU最多的系統調用函數

優化建議:
  • 內核消耗優化:
    • 是否存在過多的系統調用:批量化的方式減低系統調用的次數
    • 是否系統中的線程切換太過頻繁:單線程+隊列的模型降低線程間的切換和競爭帶來的開銷
  • 算法優化:
    加密解密/壓縮解壓等涉及數學運算的方法比較消耗CPU
    • 更優的算法
    • 空間換時間的方式
  • 終極優化:橫向擴展機器數量、縱向升級服務器硬件能力

單核CPU利用率高

排查思路:

top -Hp $pid再按1能查看到每個CPU核心的使用情況。
如果某個CPU利用率到90%以上的情況,通常是單個線程不斷地幹活導致的。

優化建議
  • 數據同步並行化
    • 對於數據備份或者同步的場景爲了保證主備機器間的一致性,使用單線程
    • 將不同的數據類型從源頭區分開,在數據同步的時候分發到不同的複製線程並行化處理
  • 業務拆解並行化
    • 對現有的業務執行路徑進行切分,提取出可以並行的

2、內存

頻繁FULL GC

  • 每次執行垃圾回收算法後並沒有騰出多少可用空間
  • 內存佔用空間依舊超出了觸發垃圾回收的臨界值馬上又進入下一輪垃圾回收過程
  • 頻繁的執行垃圾回收算法會導致CPU利用率的飆升,程序表現僵死
排查思路:定位無法被回收的對象
  • 開發機:MAT + hdump.bin文件
  • 內存過大: 修改MemoryAnalyzer.ini
  • mini版: jmap -histo:live ${pid} |sort -k 3 -g -r|less查看佔內存最大的數據結構
優化建議
  • 限制造成頻繁GC的對象數量
  • 使用隊列的地方儘可能採用有界隊列
  • 異步化調用時信息緩存到特定的集合容器,需要限流控制

內存空間夠,依舊觸發了Full GC

因爲碎片的原因導致沒有一塊連續足夠大的可用內存空間,所以必須進行full gc 進行內存回收和碎片的整理,這個過程在採用大內存的場景下回收效率相當慢

優化建議
  • 採用堆外內存替代堆內存(待深入)

後臺IO高負載造成的長時間JVM GC停頓

因爲IO原因導致卡在寫gc統計日誌上,就會導致系統的長時間不響應。

3、網絡

超時嚴重

排查思路

一般網絡延遲情況:

  • IDC ~0.1ms
  • 同城跨IDC ~5ms
  • 異地跨IDC ~30ms-100ms

這種場景可以通過ping上下游系統服務器ip來進一步確認網絡是否通暢,是否超出正常預期

優化建議
  • 數據重複率可能陡增,做好去重設計

發送緩衝區積壓

有些場景下自身系統各項資源指標正常,但是整體的吞吐量就是上不來,可能是這個問題引起。

排查思路
  • netstat -nap|grep $pid查看鏈接情況
  • 多次執行該命令看到發送區的數值幾乎沒有變化,說明發送緩衝區積壓
  • 對方接收系統可能出現異常,導致我方發送不出去
優化建議
  • 限流保護
    • 防止擊垮下游系統
    • 防止己方系統中異步請求積壓,導致GC
  • 持久化落地
    • 文件落地等應急措施
    • 防止下游系統故障影響己方上游系統

接收緩衝區積壓

  • netstat -nap|grep $pid
  • 積壓在緩衝區的數據處於內核態
  • 緩衝區積壓只是表象:
    • 用戶態內存空間不足?
    • 程序僵死?
    • CPU利用率異常?
    • Full GC?

4、磁盤

IO Util高

iostat -x %util超過70%就需要重視

在這裏插入圖片描述

需要對熱點代碼進行追蹤:

  • iotop查看到按照%io佔用百分比排列的線程
  • ID(十進制)轉換成十六進制的值
  • pid.jstack找到十六進制值對應的線程調用棧,深入分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章