線上服務 CPU 100%?一鍵定位 so easy

作者:大數據之路
來源:https://my.oschina.net/leejun2005/blog/1524687


0、背景

經常做後端服務開發的同學,或多或少都遇到過 CPU 負載特別高的問題。尤其是在週末或大半夜,突然群裡有人反饋線上機器負載特別高,不熟悉定位流程和思路的同學可能登上服務器一通手忙腳亂,定位過程百轉千回。


線上服務 CPU 100%?一鍵定位 so easy



對此,也有不少同學曾經整理過相關流程或方法論,類似把大象放進冰箱要幾步,傳統的方案一般是4步:

  1. top oder by with P:1040 // 首先按進程負載排序找到 axLoad(pid)
  2. top -Hp 進程PID:1073 // 找到相關負載 線程PID
  3. printf “0x%x\\n”線程PID: 0×431 // 將線程PID轉換為 16進制,為後面查找 jstack 日誌做準備
  4. jstack 進程PID | vim +/十六進制線程PID – // 例如:jstack 1040|vim +/0×431 -


但是對於線上問題定位來說,分秒必爭,上面的 4 步還是太繁瑣耗時了,有沒有可能封裝成為一個工具,在有問題的時候一鍵定位,秒級找到有問題的代碼行呢?

當然可以!工具鏈的成熟與否不僅體現了一個開發者的運維能力,也體現了開發者的效率意識。淘寶的oldratlee 同學就將上面的流程封裝為了一個工具:show-busy-java-threads.sh(點擊可直接下載,或參考文末鏈接下載),可以很方便的定位線上的這類問題,下面我會舉兩個例子來看實際的效果。

快速安裝使用:

source


1、java 正則表達式回溯造成 CPU 100%

線上服務 CPU 100%?一鍵定位 so easy

編譯、運行上述代碼之後,咱們就能觀察到服務器多了一個 100% CPU 的 java 進程:


線上服務 CPU 100%?一鍵定位 so easy



怎麼使用呢?

線上服務 CPU 100%?一鍵定位 so easy


示例:

線上服務 CPU 100%?一鍵定位 so easy

可以看到,一鍵直接定位異常代碼行,是不是很方便?

2、線程死鎖,程序 hang 住

線上服務 CPU 100%?一鍵定位 so easy

線上服務 CPU 100%?一鍵定位 so easy

執行之後的效果:


線上服務 CPU 100%?一鍵定位 so easy



如何用工具定位:


線上服務 CPU 100%?一鍵定位 so easy



一鍵定位:可以清晰的看到線程互相鎖住了對方等待的資源,導致死鎖,直接定位到代碼行和具體原因。

通過上面兩個例子,我想各位同學應該對這個工具和工具能解決什麼問題有了比較深刻的瞭解了,遇到 CPU 100% 問題可以從此不再慌亂。但是更多的還是依賴大家自己去實踐,畢竟實踐出真知嘛~

3、免費實用的腳本工具大禮包

除了正文提到的 show-busy-java-threads.sh,oldratlee 同學還整合和不少常見的開發、運維過程中涉及到的腳本工具,覺得特別有用的我簡單列下:

(1)show-duplicate-java-classes

偶爾會遇到本地開發、測試都正常,上線後卻莫名其妙的 class 異常,歷經千辛萬苦找到的原因竟然是 Jar衝突!這個工具就可以找出Java Lib(Java庫,即Jar文件)或Class目錄(類目錄)中的重複類。

Java開發的一個麻煩的問題是Jar衝突(即多個版本的Jar),或者說重複類。會出NoSuchMethod等的問題,還不見得當時出問題。找出有重複類的Jar,可以防患未然。

# 查找當前目錄下所有Jar中的重複類
show-duplicate-java-classes
# 查找多個指定目錄下所有Jar中的重複類

show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2
# 查找多個指定Class目錄下的重複類。 Class目錄 通過 -c 選項指定
show-duplicate-java-classes -c path/to/class_dir1 -c /path/to/class_dir2
# 查找指定Class目錄和指定目錄下所有Jar中的重複類的Jar
show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2 -c path/to/class_dir1 -c path/to/class_dir2

例如:

# 在war模塊目錄下執行,生成war文件
$ mvn install
...
# 解壓war文件,war文件中包含了應用的依賴的Jar文件
$ unzip target/*.war -d target/war
...
# 檢查重複類
$ show-duplicate-java-classes -c target/war/WEB-INF/classes target/war/WEB-INF/lib
...

(2)find-in-jars

在當前目錄下所有jar文件裡,查找類或資源文件。

用法:注意,後面Pattern是grep的 擴展正則表達式。

find-in-jars 'log4j\\.properties'
find-in-jars 'log4j\\.xml$' -d /path/to/find/directory
find-in-jars log4j\\\\.xml
find-in-jars 'log4j\\.properties|log4j\\.xml'

示例:

$ ./find-in-jars 'Service.class$'
./WEB-INF/libs/spring-2.5.6.SEC03.jar!org/springframework/stereotype/Service.class
./rpc-benchmark-0.0.1-SNAPSHOT.jar!com/taobao/rpc/benchmark/service/HelloService.class

(3)housemd pid [java_home]

很早的時候,我們使用BTrace排查問題,在感嘆BTrace的強大之餘,也曾好幾次將線上系統折騰掛掉。2012年淘寶的聚石寫了HouseMD,將常用的幾個Btrace腳本整合在一起形成一個獨立風格的應用,其核心代碼用的是Scala,HouseMD是基於字節碼技術的診斷工具, 因此除了Java以外, 任何最終以字節碼形式運行於JVM之上的語言, HouseMD都支持對它們進行診斷, 如Clojure(感謝@Killme2008提供了它的使用入門), scala, Groovy, JRuby, Jython, kotlin等.

使用housemd對java程序進行運行時跟蹤,支持的操作有:

  • 查看加載類
  • 跟蹤方法
  • 查看環境變量
  • 查看對象屬性值
  • 詳細信息請參考: https://github.com/CSUG/HouseMD/wiki/UserGuideCN


(4)jvm pid

執行jvm debug工具,包含對java棧、堆、線程、gc等狀態的查看,支持的功能有:

線上服務 CPU 100%?一鍵定位 so easy

進入jvm工具後可以輸入序號執行對應命令

可以一次執行多個命令,用分號”;”分隔,如:1;3;4;5;6

每個命令可以帶參數,用冒號”:”分隔,同一命令的參數之間用逗號分隔,如:

Enter command queue:1;5:1000,100;10:/data1/output.bin

(5)greys [@IP:PORT]

PS:目前Greys僅支持Linux/Unix/Mac上的Java6+,Windows暫時無法支持

Greys是一個JVM進程執行過程中的異常診斷工具,可以在不中斷程序執行的情況下輕鬆完成問題排查工作。和HouseMD一樣,Greys-Anatomy取名同名美劇“實習醫生格蕾”,目的是向前輩致敬。代碼編寫的時候參考了BTrace和HouseMD兩個前輩的思路。

使用greys對java程序進行運行時跟蹤(不傳參數,需要先greys -C pid,再greys)。支持的操作有:

  • 查看加載類,方法信息
  • 查看JVM當前基礎信息
  • 方法執行監控(調用量,失敗率,響應時間等)
  • 方法執行數據觀測、記錄與回放(參數,返回結果,異常信息等)
  • 方法調用追蹤渲染
  • 詳細信息請參考: https://github.com/oldmanpushcart/greys-anatomy/wiki


(6)sjk <arguments> sjk –commands sjk –help /<arguments>

使用sjk對Java診斷、性能排查、優化工具

  • ttop:監控指定jvm進程的各個線程的cpu使用情況
  • jps: 強化版
  • hh: jmap -histo強化版
  • gc: 實時報告垃圾回收信息
  • 更多信息請參考: https://github.com/aragozin/jvm-tools


分享到:


相關文章: