Arthas
是Alibaba開源的Java診斷工具。在線排查問題,無需重啓;動態跟蹤Java代碼;實時監控JVM狀態。對分秒必爭的線上異常,Arthas
可幫助咱們快速診斷相關問題。java
下載Arthas
的arthas-boot.jar
git
wget https://alibaba.github.io/arthas/arthas-boot.jar
下載arthas
以後,先來了解幫助信息,能夠經過java -jar arthas-boot.jar -h
命令查看,這裏給出了一些例子和參數說明github
[root@izwz94a0v1sz0gk4rezdcbz arthas]# java -jar arthas-boot.jar -h [INFO] arthas-boot version: 3.1.4 Usage: arthas-boot [-h] [--target-ip <value>] [--telnet-port <value>] [--http-port <value>] [--session-timeout <value>] [--arthas-home <value>] [--use-version <value>] [--repo-mirror <value>] [--versions] [--use-http] [--attach-only] [-c <value>] [-f <value>] [--height <value>] [--width <value>] [-v] [--tunnel-server <value>] [--agent-id <value>] [--stat-url <value>] [pid] Bootstrap Arthas EXAMPLES: java -jar arthas-boot.jar <pid> java -jar arthas-boot.jar --target-ip 0.0.0.0 java -jar arthas-boot.jar --telnet-port 9999 --http-port -1 java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws' java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws' --agent-id bvDOe8XbTM2pQWjF4cfw java -jar arthas-boot.jar --stat-url 'http://192.168.10.11:8080/api/stat' java -jar arthas-boot.jar -c 'sysprop; thread' <pid> java -jar arthas-boot.jar -f batch.as <pid> java -jar arthas-boot.jar --use-version 3.1.4 java -jar arthas-boot.jar --versions java -jar arthas-boot.jar --session-timeout 3600 java -jar arthas-boot.jar --attach-only java -jar arthas-boot.jar --repo-mirror aliyun --use-http WIKI: https://alibaba.github.io/arthas Options and Arguments: -h,--help Print usage --target-ip <value> The target jvm listen ip, default 127.0.0.1 --telnet-port <value> The target jvm listen telnet port, default 3658 --http-port <value> The target jvm listen http port, default 8563 --session-timeout <value> The session timeout seconds, default 1800 (30min) --arthas-home <value> The arthas home --use-version <value> Use special version arthas --repo-mirror <value> Use special maven repository mirror, value is center/aliyun or http repo url. --versions List local and remote arthas versions --use-http Enforce use http to download, default use https --attach-only Attach target process only, do not connect -c,--command <value> Command to execute, multiple commands separated by ; -f,--batch-file <value> The batch file to execute --height <value> arthas-client terminal height --width <value> arthas-client terminal width -v,--verbose Verbose, print debug info. --tunnel-server <value> The tunnel server url --agent-id <value> The agent id register to tunnel server --stat-url <value> The report stat url <pid> Target pid
啓動arthas
以前,先啓動一個springboot
的應用。該demo
在地址https://github.com/yangtao...正則表達式
java -jar ytao-springboot-demo.jar
啓動arthas-boot.jar
命令spring
java -jar arthas-boot.jar
這裏注意須要啓動demo
和arthas
使用同一權限用戶,不然使用attach機制獲取不到進程信息(這裏剛使用時沒注意,遇到過這個問題)。
例:root
用戶啓動 demo
,u1
用戶啓動arthas
時,打印信息Can not find java process. Try to pass <pid> in command line.
express
查看源碼,在獲取進程以後,添加日誌輸出。結果爲空,返回-1
,判斷結果小於0
時,直接退出。api
啓動類Bootstrap#main
的代碼springboot
進程工具類ProcessUtils#select
的代碼bash
經過上面也分析到,咱們啓動arthas
以前,必需要先啓動咱們的目標進程,不然arthas
可能沒法啓動。session
使用root
用戶啓動成功界面
選擇java進程,這裏咱們的ytao-springboot-demo
是 1,選擇後會有鏈接信息
[INFO] arthas home: /root/.arthas/lib/3.1.4/arthas [INFO] Try to attach process 22005 [INFO] Attach process 22005 success. [INFO] arthas-client connect 127.0.0.1 3658 ,---. ,------. ,--------.,--. ,--. ,---. ,---. / O \ | .--. ''--. .--'| '--' | / O \ ' .-' | .-. || '--'.' | | | .--. || .-. |`. `-. | | | || |\ \ | | | | | || | | |.-' | `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' wiki https://alibaba.github.io/arthas tutorials https://alibaba.github.io/arthas/arthas-tutorials version 3.1.4 pid 17339 time 2019-10-17 02:29:06
使用dashboard
命令,能夠查看線程,內存,GC,以及Runtime信息
有時咱們會遇到線上代碼運行結果不是咱們指望的結果,有種狀況就是線上代碼不是咱們想要的版本,可是要查看的話,須要下載後再進行反編譯。
這時arthas
的jad
能夠幫助咱們線上進行即時反編譯,確認代碼是否符合咱們的版本。
jad com.ytao.service.UserServiceImpl
使用watch
命令能夠查看函數的執行信息。watch
的參數列表(來自官網)
參數 | 參數說明 |
---|---|
class-pattern | 類名錶達式匹配 |
method-pattern | 方法名錶達式匹配 |
express | 觀察表達式 |
condition-express | 條件表達式 |
[b] | 在方法調用以前觀察 |
[e] | 在方法異常以後觀察 |
[s] | 在方法返回以後觀察 |
[f] | 在方法結束以後(正常返回和異常返回)觀察 |
[E] | 開啓正則表達式匹配,默認爲通配符匹配 |
[x:] | 指定輸出結果的屬性遍歷深度,默認爲 1 |
當咱們遇到線上數據bug
時,咱們通常處理的手段就是開發環境模擬線上數據,從生產日誌中查找線索,再或者遠程debug
。以上無論哪一種排查手段,相對都是比較麻煩。
這時Arthas的watch
能夠幫助咱們查看實時的代碼執行狀況。使用觀察表達式能夠查看函數的參數
,返回值
,異常信息
。觀察表達式主要由OGNL
表達式組成,因此能夠編寫OGNL
表達式來執行。
觀察表達式的變量
變量 | 變量說明 |
---|---|
params | 函數的入參 |
returnObj | 函數的返回值 |
throwExp | 異常信息 |
target | 當前對象 |
查看一個函數的入參和返回值
watch com.ytao.service.UserServiceImpl getUser "{params,returnObj}"
打印信息isEmpty=false;size=1
能夠看到參數爲非空,參數數量爲一個。查看具體入參信息
watch com.ytao.service.UserServiceImpl getUser "{params[0],returnObj}"
查看異常信息
watch com.ytao.service.UserServiceImpl getUser "throwExp"
當咱們傳入一個參數爲-1
時,打印出咱們定義的非法參數異常
watch
除了觀察表達式外,還能使用條件表達式
,以及觀察事件點
。
注意使用觀察事件點時,有些觀察表達式的變量不必定存在,好比使用-b
時,返回值和異常信息都爲空。
有時咱們排查某個函數,不能立刻獲取到函數的信息,arthas
給提供的後臺異步任務
能夠幫助咱們記錄日誌。使用方式和Linux的相似。
watch com.ytao.service.UserServiceImpl getUser "{params,returnObj}" > /log/w.log &
查看異步保存的日誌
上面所介紹的watch
能夠排查函數的調用狀況,比較適用在已知當次調用可能存在的狀況後,查看信息。若是一個函數調用n次後,有幾回爲執行異常,咱們要去找出這些異常的調用,在watch
中排查就不怎麼方便了。
使用tt
命令能夠較方便查看異常的調用及信息。對com.ytao.service.UserServiceImpl#getUser
的函數查看,-t
是每次調用該函數都會記錄
tt -t com.ytao.service.UserServiceImpl getUser
記錄信息
查看全部記錄
tt -l
查看指定函數記錄
tt -s 'method.name=="getUser"'
輸出信息說明
表格字段 | 字段解釋 |
---|---|
INDEX | 時間片斷記錄編號,每個編號表明着一次調用,後續tt還有不少命令都是基於此編號指定記錄操做,很是重要。 |
TIMESTAMP | 方法執行的本機時間,記錄了這個時間片斷所發生的本機時間 |
COST(ms) | 方法執行的耗時 |
IS-RET | 方法是否以正常返回的形式結束 |
IS-EXP | 方法是否以拋異常的形式結束 |
OBJECT | 執行對象的hashCode(),注意,曾經有人誤認爲是對象在JVM中的內存地址,但很遺憾他不是。但他能幫助你簡單的標記當前執行方法的類實體 |
CLASS | 執行的類名 |
METHOD | 執行的方法名 |
從上面參數中咱們看到1003
調用是以拋異常的形式結束,由於tt
會記錄每次調用的信息,因此咱們能夠查看1003
的詳細信息
tt -i 1003
咱們常會遇到調用某個api時rt過長,咱們就要找出調用鏈上的某個或幾個函數進行優化,咱們一般定位幾個可能的錨點,打印各個錨點間的rt。或者從日誌中找出日誌打印的時間點計算出時間差,無論使用哪一種方法都比較繁瑣。當使用arthas
的trace
命令能夠輕鬆的完成咱們的需求。
trace
參數說明
參數 | 參數說明 |
---|---|
class-pattern | 類名錶達式匹配 |
method-pattern | 方法名錶達式匹配 |
condition-express | 條件表達式 |
[E] | 開啓正則表達式匹配,默認爲通配符匹配 |
[n:] | 命令執行次數 |
#cost | 方法執行耗時 |
使用trace
輸出com.ytao.controller.UserController#getUser
的信息
trace com.ytao.service.UserServiceImpl getUser
輸出結果
在實際使用使用排查過程當中,爲了減小無用信息的輸出,咱們通常會使用#cost
過濾耗時不長和jdk自帶的函數,能夠忽略的調用,減小信息的輸出。例如:過濾掉小於1ms
的調用
trace com.ytao.service.UserServiceImpl getUser '#cost > 1'
當咱們查找出bug,想要快速上線拯救蒼生的時候,Arthas
爲咱們準備了redefine
命令來實現熱更新。
儘管如今都在倡導jad
/mc
/redefine
熱更一條龍,可是線上代碼建議本地編譯好後再進行替換,避免手誤操做。
首先先在UserServiceImpl
中添加一行代碼
獲取classLoaderHash
,經過sc
命令獲取類的信息
sc -d *UserServiceImpl
執行redefine
修改的類
redefine -c 1d56ce6a /usr/local/jar/UserServiceImpl.class
經過打印的信息驗證是否更新UserServiceImpl
類
Arthas
的使用,除了上文中所講解到的,還有一些其餘的診斷功能,這只是我我的使用的方法。可是使用該類工具必定要有套組合拳,對排查問題過程當中,遇到問題有對應的排查手段,並不是盲目排查。
我的博客: https://ytao.top
個人公衆號 ytao