天天看點

Arthas 實踐——生産環境排查 CPU 飚高問題

作者 | 李昊(可以養肥)

【Arthas 官方社群正在舉行征文活動,參加即有獎品拿~

點選投稿

生産環境 CPU 告警:

 13:40 收到我們的生産環境伺服器綠版 CUP 超負載告警通知。

Arthas 實踐——生産環境排查 CPU 飚高問題

此時心裡隻有一個想法,重新開機大法好,馬上登入伺服器,執行 top 發現程序 30247 和 28337 占用 CPU 為 200 多和100 多基本占用了 4 核的 3 核,整個過程大概用時 30 秒,維護群依然很平靜,營運的電話也沒打過來,這時候我斷定,這次問題應該影響面很小,使用者可能也暫時沒有發現,好吧,還有時間做排查。

Arthas 實踐——生産環境排查 CPU 飚高問題

Arthas排查過程:

  • 開啟 Arthas 工具找到對應的 30247 運單子產品和 28337 支付子產品,選擇運單子產品進入:
java -jar arthas-boot.jar           
Arthas 實踐——生産環境排查 CPU 飚高問題
  • 執行 dashboard 指令,線程 35 和 12042 不正常 CUP 占用 49%:
dashboard           
Arthas 實踐——生産環境排查 CPU 飚高問題
  • 執行 thread 35  thread 12042 定位代碼行:
thread 35
thread 12042           
Arthas 實踐——生産環境排查 CPU 飚高問題
  • 檢視代碼,業務需求為生成一個至少包含 2 個數字的随機字元串,我們使用的統一的工具類方法,該方法中先通過

    UUID.randomUUID()

    随機出一個 10 位的字元池,然後再從這個字元池中随機需要位數的字元串,如果随機出來的 10 位字元池中都是字母,則二次随機時候就會出現死循環,問題代碼如下:
public static String getRandomStr(boolean numberFlag, int length) {
    String retStr = "";
    String strTable =
        numberFlag
            ? UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10)
            : "1234567890abcdefghijkmnpqrstuvwxyz";
    int len = strTable.length();
    boolean bDone = true;
    do {
      retStr = "";
      int count = 0;
      for (int i = 0; i < length; i++) {
        double dblR = Math.random() * len;
        int intR = (int) Math.floor(dblR);
        char c = strTable.charAt(intR);
        if (('0' <= c) && (c <= '9')) {
          count++;
        }
        retStr += strTable.charAt(intR);
      }
      if (count >= 2) {
        bDone = false;
      }
    } while (bDone);
    return retStr;
  }           
  • 線下模拟不到二萬次

    UUID.randomUUID()

    前十位會出現一次全字母的情況。
Arthas 實踐——生産環境排查 CPU 飚高問題
  • 最終原因是死循環導緻的 CPU 飚高,修複代碼,增加是否都是字母的判斷,第一次随機出來的 10 位字元池都是字母,則重新随機。

Arthas 常用指令:

安裝

curl -O

arthas.aliyun.com/arthas-boot…

java -jar arthas-boot.jar

基礎指令

help——檢視指令幫助資訊

cat——列印檔案内容,和 linux 裡的 cat 指令類似

echo–列印參數,和 linux 裡的 echo 指令類似

grep——比對查找,和 linux 裡的 grep 指令類似

tee——複制标準輸入到标準輸出和指定的檔案,和 linux 裡的 tee 指令類似

pwd——傳回目前的工作目錄,和 linux 指令類似

cls——清空目前螢幕區域

session——檢視目前會話的資訊

reset——重置增強類,将被 Arthas 增強過的類全部還原,Arthas 服務端關閉時會重置所有增強過的類

version——輸出目前目标 Java 程序所加載的 Arthas 版本号

history——列印指令曆史

quit——退出目前 Arthas 用戶端,其他 Arthas 用戶端不受影響

stop——關閉 Arthas 服務端,所有 Arthas 用戶端全部退出

keymap——Arthas 快捷鍵清單及自定義快捷鍵

jvm相關

dashboard——目前系統的實時資料面闆

thread——檢視目前 JVM 的線程堆棧資訊

jvm——檢視目前 JVM 的資訊

sysprop——檢視和修改 JVM 的系統屬性

sysenv——檢視 JVM 的環境變量

vmoption——檢視和修改 JVM 裡診斷相關的 option

perfcounter——檢視目前 JVM 的 Perf Counter 資訊

logger——檢視和修改 logger

getstatic——檢視類的靜态屬性

ognl——執行 ognl 表達式

mbean——檢視 Mbean 的資訊

heapdump——dump java heap, 類似 jmap 指令的 heap dump 功能

class/classloader相關

sc——檢視 JVM 已加載的類資訊

sm——檢視已加載類的方法資訊

jad——反編譯指定已加載類的源碼

mc——記憶體編譯器,記憶體編譯 .java 檔案為 .class 檔案

redefine——加載外部的 .class 檔案,redefine 到 JVM 裡

dump——dump 已加載類的 byte code 到特定目錄

classloader——檢視 classloader 的繼承樹,urls,類加載資訊,使用 classloader 去 getResource

monitor/watch/trace相關

  • monitor 方法執行監控

monitor -c 5 demo.MathGame primeFactors

-c 5 未統計周期預設 120s

  • watch 能觀察到的範圍為:傳回值、抛出異常、入參

watch demo.MathGame primeFactors “{params,target,returnObj}” -x 2 -b -s -n 2

-x 2 輸出結果的屬性周遊深度

-b 方法調用前

-s 方法傳回後

-n 2 執行2次

watch demo.MathGame primeFactors “{params[0],throwExp}” -e -x 2

-e表示抛出異常時才觸發

  • trace 方法内部調用路徑,并輸出方法路徑上的每個節點上耗時

trace demo.MathGame run

Arthas 征文活動火熱進行中

Arthas 官方正在舉行征文活動,如果你有:

  • 使用 Arthas 排查過的問題
  • 對 Arthas 進行源碼解讀
  • 對 Arthas 提出建議
  • 不限,其它與 Arthas 有關的内容

歡迎參加征文活動,還有獎品拿哦~