arthas中文直譯過來叫阿爾薩斯,是阿里巴巴開源的java應(yīng)用診斷工具,在線排查問題,無需重啟服務(wù),實(shí)時(shí)監(jiān)控jvm狀態(tài)。支持JDK6以上版本,支持Linux/Mac/Window操作系統(tǒng)。
采用命令行交換方式,tab鍵命令自動(dòng)補(bǔ)全,而且兼容linux系統(tǒng)部分命令,如:grep,ctrl+i清屏,ctrl+a跳到行首,ctrl+c終止命令等
如果你還在使用jdk原生jstat、jmap等命令排查問題,那么,強(qiáng)烈建議你使用arthas。本文介紹arthas的下載安裝、啟動(dòng)、常用命令、退出、卸載以及常見問題的調(diào)試步驟
arthas安裝分為快速安裝和全量安裝,快速安裝只下載arthas-boot.jar。全量安裝是下載一個(gè)壓縮包,壓縮包中包含arthas-boot.jar、測(cè)試demo和封裝好的啟動(dòng)腳本等文件,一般我們使用快速安裝就可以了
快速安裝
linux系統(tǒng)中安裝可以用curl命令從阿里云官方網(wǎng)站下載
curl -O?https://arthas.aliyun.com/arthas-boot.jar
windows系統(tǒng)中安裝用瀏覽器打開如下地址會(huì)提示下載
https://arthas.aliyun.com/arthas-boot.jar
全量安裝
linux全量安裝需要先下載執(zhí)行腳本
curl -L?https://arthas.aliyun.com/install.sh?|?sh
下載完成后會(huì)在當(dāng)前目錄生成as.sh腳本,執(zhí)行腳本 ./as.sh 后會(huì)自動(dòng)下載全量安裝包,默認(rèn)保存在~/.arthas/lib目錄下。修改as.sh腳本可以更改默認(rèn)保存路徑
windows全量安裝只需要用瀏覽器打開下載地址就會(huì)提示下載
https://arthas.aliyun.com/download/latest_version?mirror=aliyun
全量安裝包的文件夾名稱為arthas,目錄結(jié)構(gòu)如下
啟動(dòng)
啟動(dòng)之前需要明確要監(jiān)聽哪個(gè)java程序,并找到這個(gè)java程序的進(jìn)程id。當(dāng)前登錄用戶必須對(duì)要監(jiān)聽的進(jìn)程有可操作權(quán)限,否則會(huì)報(bào)錯(cuò)
linux中使用ps或jps命令可以找到j(luò)ava程序的進(jìn)程id
ps -ef?|?grep?java?
jps?-mlv
windows中打開任務(wù)管理器可以找到對(duì)應(yīng)程序的進(jìn)程id
執(zhí)行命令啟動(dòng)arthas
java -jar arthas-boot.jar
啟動(dòng)后會(huì)提示選擇監(jiān)聽哪個(gè)進(jìn)程id,輸入對(duì)應(yīng)的序號(hào)即可。我要監(jiān)聽的進(jìn)程id是19646,也就是序號(hào)2
輸入2之后敲回車,啟動(dòng)成功如下圖
啟動(dòng)時(shí)可以直接指定pid,就不用在啟動(dòng)過程中再輸入序號(hào)了
java -jar arthas-boot.jar 19646
如果安裝時(shí)選擇了全量安裝,那么也可以通過腳本啟動(dòng),linux系統(tǒng)使用as.sh腳本,windows系統(tǒng)使用as.bat腳本
查看dashboard
dashboard命令可以查看cpu、線程狀態(tài),內(nèi)存信息、GC情況和jdk版本等信息
圖中字段解讀
ID:?Java中的線程ID,注意這個(gè)ID不能跟jstack中的nativeID一一對(duì)應(yīng) NAME:?線程名稱 GROUP:?線程組名稱 PRIORITY:?線程優(yōu)先級(jí),?1~10之間的數(shù)字,越大表示優(yōu)先級(jí)越高 STATE:?線程的狀態(tài) CPU%:?線程消耗的cpu占比,采樣間隔100ms,將所有線程在這100ms內(nèi)的cpu使用量求和,再算出每個(gè)線程的cpu使用占比。 TIME:?線程運(yùn)行總時(shí)間,格式為?分:秒 INTERRUPTED:?線程當(dāng)前的中斷狀態(tài) DAEMON:?是否是守護(hù)線程
監(jiān)控頁面會(huì)實(shí)時(shí)刷新,默認(rèn)每5000毫秒(5秒)刷新一次??梢酝ㄟ^ - i 參數(shù)指定刷新頻率,-n 參數(shù)指定刷新次數(shù)。這個(gè)統(tǒng)計(jì)會(huì)有一定的開銷,從截圖中也可以看到arthas的cpu占比較大,所以刷新頻率不要太高,建議5秒以上,刷新次數(shù)建議10次以內(nèi)
//?每10秒刷新一次,3次后停止 dashboard?-i 10000 -n 3
查看線程
使用thread命令可以查看線程的狀態(tài),顯示的結(jié)果實(shí)際就是dashboard結(jié)果的第一欄
thread命令可以追加參數(shù)
id:可以查看指定線程id的堆棧信息?
-n value:找出最忙的value個(gè)線程,并打印堆棧信息?
-b:找出當(dāng)前正在阻塞其他線程的線程?
-i value:指定采樣cpu占比的時(shí)間間隔,默認(rèn)為100ms。
打印線程id=24的堆棧信息
打印當(dāng)前最忙的3個(gè)線程的堆棧信息
打印正在阻塞其他線程的線程
指定統(tǒng)計(jì)線程cpu占比的時(shí)間間隔,單位:毫秒。因?yàn)榻y(tǒng)計(jì)cpu占比會(huì)有一定的資源消耗,所以時(shí)間間隔不要太小,建議100毫秒以上
thead?-i 200
反編譯
使用jad可以對(duì)代碼進(jìn)行反編譯,反編譯過來的代碼可能會(huì)有語法錯(cuò)誤,但不影響閱讀。比較貼心的是,反編譯過來的代碼語法高亮,方便閱讀
類名支持全路徑,同時(shí)也支持模糊匹配,下面兩個(gè)命令可以達(dá)到相同的效果
jad com.helianxiaowu.demo.ThreadBlock jad *ThreadBlock
也可以對(duì)類中的某一個(gè)方法進(jìn)行反編譯,只需要在類名后面加上方法名即可
反編譯過來的代碼默認(rèn)攜帶ClassLoader信息,使用 --source-only 選項(xiàng)可以去除ClassLoader信息
使用quit或exit會(huì)退出arthas操作界面,但arthas進(jìn)程還在,這時(shí)當(dāng)你想監(jiān)聽別的java進(jìn)程時(shí)會(huì)報(bào)錯(cuò)。因?yàn)閍rthas默認(rèn)使用的是3658端口,所以這時(shí)會(huì)報(bào)錯(cuò)3658端口被別的進(jìn)程占用。
使用shutdown或stop可以結(jié)束arthas,結(jié)束后可以監(jiān)聽別的進(jìn)程id
出現(xiàn)端口被占用報(bào)錯(cuò)時(shí),可以再次啟動(dòng)進(jìn)入剛才監(jiān)聽的進(jìn)程或者使用telnet進(jìn)入剛才監(jiān)聽的arthas進(jìn)程界面,執(zhí)行shutdown或stop結(jié)束監(jiān)聽
telnet?localhost 3658
卸載
linu系統(tǒng)中執(zhí)行如下命令進(jìn)行卸載
rm?-rf?~/.arthas/ rm?-rf?~/logs/arthas
window下需要進(jìn)入C盤當(dāng)前用戶的目錄,找到 .arthas目錄和logs/arthas目錄進(jìn)行刪除
java程序中,頻繁GC、鏈接沒有釋放、線程數(shù)量過多導(dǎo)致頻繁的進(jìn)行切換、線程被阻塞、死循環(huán)等原因是造成cpu飆升的主要原因。
通過arthas的dashboard命令可以看到GC的回收次數(shù)和時(shí)間,現(xiàn)在大部分程序都是使用spring進(jìn)行對(duì)象管理,不會(huì)出現(xiàn)創(chuàng)建大量實(shí)例對(duì)象的情況。數(shù)據(jù)庫鏈接、IO、HTTP鏈接都使用的鏈接池,也很少出現(xiàn)鏈接沒有釋放的問題。所以,JVM頻繁進(jìn)行GC操作,很有可能是內(nèi)存設(shè)置不合理,可以使用如下參數(shù)指定內(nèi)存
JAVA_OPTS="-server?-Xms256m?-Xmx512m?-XX:PermSize=64M?-XX:MaxPermSize=128m"
線程數(shù)量過多導(dǎo)致頻繁進(jìn)行線程切換,基本可以斷定當(dāng)前服務(wù)支撐不了現(xiàn)有的并發(fā)了,需要增加服務(wù)器資源或者增加負(fù)載
現(xiàn)在來模擬一個(gè)cpu飆升的問題排查過程
首先啟動(dòng)測(cè)試程序,模擬cpu升高的情況
然后啟動(dòng)arthas,選擇測(cè)試程序?qū)?yīng)的進(jìn)程進(jìn)行監(jiān)控。輸入dashboard命令,可以看到id=10的這個(gè)線程占用cpu過高
打印id=10的線程堆棧信息,可以看到這個(gè)線程正在執(zhí)行high()方法
反編譯high方法,查看源碼,可以看到進(jìn)行了死循環(huán),所以cpu會(huì)飆升
一個(gè)接口調(diào)用,好長(zhǎng)時(shí)間才能收到響應(yīng),接口邏輯復(fù)雜,排查起來特別困難,不知從何下手?下面帶你一步步找到問題
找到調(diào)用耗時(shí)較長(zhǎng)的接口,這里測(cè)試使用的是MethodDemo類中的slow()方法。
啟動(dòng)測(cè)試程序,調(diào)用slow方法,可以看到該方法耗時(shí)足足10秒,確實(shí)很慢
在arthas監(jiān)控頁面輸入如下命令對(duì)這個(gè)方法進(jìn)行耗時(shí)統(tǒng)計(jì)
trace *MethodDemo?slow
在統(tǒng)計(jì)結(jié)果中,能看到每個(gè)方法的調(diào)用時(shí)長(zhǎng)
反編譯slow方法,發(fā)現(xiàn)代碼進(jìn)行了sleep操作,所以耗時(shí)較長(zhǎng)
trace命令是統(tǒng)計(jì)方法的內(nèi)部調(diào)用路徑,并為每個(gè)調(diào)用路徑統(tǒng)計(jì)耗時(shí)。trace命令需要指定類名和方法名,支持模糊匹配
線程阻塞會(huì)導(dǎo)致并發(fā)量上不去、cpu占用過高,降低系統(tǒng)整體性能,嚴(yán)重時(shí)會(huì)導(dǎo)致系統(tǒng)崩潰
啟動(dòng)測(cè)試程序,調(diào)用演示線程阻塞的方法
進(jìn)入arthas監(jiān)控頁面,找到目前正在阻塞其他線程的線程,可以看到loop方法中正在鎖定一個(gè)字符串,阻塞了其他線程
反編譯loop方法,可以看到使用了synchronized進(jìn)行了同步操作,阻塞了其他線程
由于篇幅有限,本文只講一些arthas常用操作,后期會(huì)再出一篇高級(jí)操作,包括webconsole遠(yuǎn)程監(jiān)控服務(wù)器、ognl表達(dá)式、封裝docker鏡像等。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!