Arthas 使用指北:線上排障別再全靠“猜”

前言

有些線上問題,乍一看像玄學。

接口突然變慢了,日志沒報錯,機器負載也不高,開發(fā)同學圍著屏幕看了半天,最后得出一個非常有技術含量的結(jié)論:再觀察觀察。

如果你也經(jīng)歷過這種場面,那大概率會需要 Arthas。

它不是銀彈,但它非常像一個能隨時插進 JVM 里“看現(xiàn)場”的老師傅。程序已經(jīng)跑起來了,不用重啟,不用提前埋一堆日志,也不用一邊改代碼一邊祈禱“希望這次能復現(xiàn)”。很多時候,Arthas 的價值就一句話:

出問題的時候,它能讓你少靠腦補,多看事實。

這篇文章不打算把 Arthas 所有命令都鋪滿一屏,那樣讀完只會讓人想關網(wǎng)頁。我們就聊最常用、最接地氣的一部分,爭取做到:

  • 看得懂
  • 用得上
  • 下次線上出事時,能想起來先開 Arthas,而不是先拜祖師爺

一、Arthas 到底是干嘛的?

簡單說,Arthas 是一個 Java 診斷工具,可以在應用運行時查看類、方法、線程、JVM 狀態(tài),還能動態(tài)跟蹤方法調(diào)用、觀察參數(shù)和返回值,甚至臨時執(zhí)行一些排查動作。

你可以把它理解成:

  • top、jstack、日志、臨時調(diào)試輸出的一個“加強縫合版”
  • 給線上 JVM 開了一個“觀察窗”
  • 程序員深夜救火時,情緒穩(wěn)定器

它最適合的場景一般有這些:

  • 某個接口為什么變慢了
  • 某個方法到底有沒有被調(diào)用
  • 傳進去的參數(shù)到底是什么鬼
  • 返回值為什么和我想的不一樣
  • CPU 飆高到底是哪幾個線程在鬧
  • 某個類是不是我以為的那個版本

二、先啟動起來

最常見的啟動方式,一般是這樣:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

運行后,它會列出當前機器上的 Java 進程,比如:

[1]: 12345 demo-application.jar
[2]: 23456 another-service.jar

輸入對應編號,Arthas 就會 attach 到目標進程。

這一步的感覺很像:

“你先別慌,讓我進去看看你腦子里現(xiàn)在到底在跑什么?!?/p>

如果你用的是 Spring Boot、Tomcat、微服務應用,流程都差不多。選中進程后,會進入 Arthas 命令行界面,接下來就能開始排查。


三、先記住這幾個高頻命令

Arthas 命令不少,但真正常用的,先掌握下面這些就夠你打很多場仗了。

1. dashboard:先看大盤,別一上來就瞎追

dashboard

它會展示當前 JVM 的一些整體信息,比如:

  • 線程數(shù)量
  • 內(nèi)存使用情況
  • GC 情況
  • 運行狀態(tài)

適合在剛連上系統(tǒng)時先掃一眼。

很多人排障像刑偵劇里的熱血新人,一上來就沖方法級別追蹤。其實更穩(wěn)妥的做法是先看全局:線程多不多?GC 抖不抖?是不是整體就已經(jīng)不正常了?

dashboard 就像醫(yī)生量血壓,雖然不能直接告訴你病根,但至少能先判斷病人是不是已經(jīng)快拍桌子了。


2. thread:誰在吃 CPU,一看便知

thread

如果你懷疑 CPU 高,可以直接看最忙的線程:

thread -n 5

這個命令會列出最占 CPU 的幾個線程,還能看到線程狀態(tài)。

如果某臺機器 CPU 飆得跟起飛一樣,這個命令特別實用。你可以先定位“是誰最能折騰”,再順著線程棧繼續(xù)查。

常見思路是:

  1. 先用 thread -n 5 找出高 CPU 線程
  2. 看線程棧在跑什么代碼
  3. 再結(jié)合業(yè)務判斷是不是死循環(huán)、頻繁重試、鎖競爭或者某段邏輯特別重

很多線上 CPU 問題,說白了不是 JVM 發(fā)神經(jīng),而是代碼在努力把服務器送走。


3. sc:確認類到底在不在

sc -d com.example.demo.service.UserService

sc 是 search class,用來查類的信息。

常見用途:

  • 這個類到底有沒有加載
  • 是哪個 ClassLoader 加載的
  • 類的源碼位置、類信息對不對

如果你懷疑“我明明改了代碼為什么沒生效”,那先別急著懷疑人生,先用 sc 看看加載的到底是不是你以為的那個類。

線上最怕的不是 bug,而是你以為線上跑的是 A,結(jié)果它跑的是 B,還特別自信。


4. jad:反編譯看看現(xiàn)場代碼

jad com.example.demo.service.UserService

這個命令非常實用。它可以把 JVM 里已經(jīng)加載的類反編譯出來。

有什么價值?

  • 看線上運行的代碼到底長什么樣
  • 排查部署包和本地代碼是不是不一致
  • 驗證某個分支邏輯到底有沒有被打進去

很多時候,本地代碼、倉庫代碼、構建產(chǎn)物、線上運行代碼,這四位選手并不一定意見統(tǒng)一。
jad 的作用,就是讓你停止爭論,直接看證據(jù)。


5. sm:查某個類里有哪些方法

sm com.example.demo.service.UserService

如果你只記得類名,不記得具體方法簽名,可以先用 sm 看方法列表。

比如你想觀察一個方法,但名字記混了,或者重載太多,這時候先 sm 一下,比硬著頭皮亂寫要靠譜。

這命令像通訊錄:

“人我認識,但全名一下子想不起來,你先讓我翻一下?!?/p>


四、真正干活的幾個命令

上面的命令偏“看信息”,下面這些則更像“直接盯現(xiàn)場”。

也是 Arthas 最容易讓人上頭的部分。


1. watch:看方法參數(shù)、返回值、異常

這是最常用的命令之一。

比如:

watch com.example.demo.service.UserService getUser '{params, returnObj, throwExp}' -x 2

它的意思大概是:

  • 觀察 UserServicegetUser 方法
  • 輸出參數(shù)、返回值、異常信息
  • -x 2 表示展開對象層級

這個命令很適合回答下面這些靈魂拷問:

  • 這個方法到底收到了什么參數(shù)?
  • 為什么查出來是 null?
  • 為什么它拋異常了?
  • 調(diào)用鏈上游是不是傳了臟數(shù)據(jù)?

如果日志沒打夠,watch 就特別像臨時補了個高清監(jiān)控。

不過要注意,線上使用時別一把梭觀察太寬泛的方法,尤其是高頻調(diào)用的方法。否則你本來是去排障的,結(jié)果變成了手動制造更多輸出。

建議控制范圍:

  • 盡量指定具體類和方法
  • 必要時加條件表達式
  • 先看少量樣本,別上來就“全量圍觀”

2. trace:慢在哪一層,給我攤開講

trace com.example.demo.controller.UserController queryUser

trace 可以追蹤一個方法內(nèi)部的調(diào)用耗時。

比如一個接口慢,你不確定慢在:

  • 查數(shù)據(jù)庫
  • 調(diào)遠程服務
  • 數(shù)據(jù)轉(zhuǎn)換
  • 某個 if 分支里的神秘邏輯

這時候 trace 很有用,它會把調(diào)用路徑和各層耗時列出來。

排查性能問題時,這命令基本屬于“別廢話,直接上證據(jù)”。

一個常見場景:

你以為慢是數(shù)據(jù)庫問題,結(jié)果一 trace,發(fā)現(xiàn) 80% 時間都花在 JSON 轉(zhuǎn)換上。
這時候你就會明白,很多性能問題不是“架構不行”,而是代碼在偷偷干體力活。


3. tt:記錄方法調(diào)用,像回放錄像

tt 全稱是 Time Tunnel,時間隧道。

名字很炫,功能也確實挺能打。

比如:

tt -t com.example.demo.service.OrderService createOrder

它會把這個方法的調(diào)用記錄下來。之后你可以查看這些調(diào)用記錄:

tt -l

還可以指定某條記錄查看詳情:

tt -i 1000

適合什么場景?

  • 某個方法偶發(fā)異常,不容易穩(wěn)定復現(xiàn)
  • 你想保留調(diào)用現(xiàn)場,后面慢慢看
  • 想對同一個問題樣本反復分析

如果說 watch 像實時監(jiān)控,那 tt 就更像 DVR 回放。
問題發(fā)生的時候先錄下來,事后再一幀一幀看,氣質(zhì)都從慌張排障變成了從容辦案。


4. monitor:統(tǒng)計方法調(diào)用情況

monitor -c 5 com.example.demo.service.UserService getUser

這個命令會周期性統(tǒng)計某個方法的調(diào)用指標,比如:

  • 調(diào)用次數(shù)
  • 成功次數(shù)
  • 失敗次數(shù)
  • 平均響應時間

適合觀察一段時間內(nèi)的方法表現(xiàn),而不是只看單次調(diào)用。

比如接口報錯率升高,你想知道:

  • 到底失敗多不多
  • 是持續(xù)失敗還是偶發(fā)失敗
  • 平均耗時是不是明顯上升了

這時候 monitor 很順手。

它像值班表,不負責講故事,但很適合告訴你:“這個人最近表現(xiàn)確實不太對勁?!?/p>


五、幾個很實戰(zhàn)的排查場景

光講命令容易看完就忘。下面直接上幾個常見場景。

場景一:接口很慢,但不知道慢在哪

思路可以這么走:

  1. dashboard 看整體 JVM 狀態(tài)
  2. thread -n 5 看有沒有線程異常繁忙
  3. trace 跟蹤目標接口方法耗時
  4. 必要時對關鍵方法再用 watch 看參數(shù)和返回值

適合的命令示例:

trace com.example.demo.controller.OrderController submit
watch com.example.demo.service.OrderService createOrder '{params, returnObj}' -x 2

這個流程的核心原則是:

先看全局,再盯局部;先定位范圍,再下鉆細節(jié)。

不要一上來就對整個系統(tǒng)瘋狂 watch,那不是排障,那是行為藝術。


場景二:接口返回結(jié)果不對

比如用戶說:“這個接口查出來的數(shù)據(jù)不對。”

先別急著甩鍋數(shù)據(jù)庫、緩存、第三方接口和水逆。

可以這樣查:

  1. watch 看 controller 或 service 方法入?yún)?/li>
  2. 看返回值是不是從這里開始歪的
  3. 如果邏輯復雜,用 trace 看分支耗時和調(diào)用過程
  4. jad 看線上實際代碼是不是你預期的版本

示例:

watch com.example.demo.service.UserProfileService queryProfile '{params, returnObj, throwExp}' -x 3
jad com.example.demo.service.UserProfileService

很多“結(jié)果不對”的問題,最后都不是框架鍋,而是某個參數(shù)一路傳著傳著,半路就長歪了。


場景三:偶發(fā)異常,日志又不完整

這個最煩。

因為它不穩(wěn)定、難復現(xiàn)、還喜歡在你下班前十分鐘出現(xiàn)。

這時候可以優(yōu)先考慮:

tt -t com.example.demo.service.PaymentService pay

把調(diào)用先錄下來,等異常出現(xiàn)后再:

tt -l
tt -i 1001

這樣至少能把出問題那次調(diào)用的參數(shù)、返回、異常現(xiàn)場抓住。

有時候排障最痛苦的不是問題難,而是你根本沒拿到現(xiàn)場。
tt 的意義,就是幫你把“案發(fā)錄像”留住。


六、Arthas 不是越猛越好,用的時候要有分寸

這部分很重要。

Arthas 很強,但不是讓你在線上隨便開“上帝視角”的理由。命令用得不克制,可能會帶來額外開銷,尤其是:

  • 盯高頻方法
  • 打印大對象
  • 觀察范圍過寬
  • 長時間持續(xù)輸出

幾個實用建議:

  • 先縮小目標,不要一把抓全服務
  • 優(yōu)先針對具體類、具體方法
  • 對象展開層級別開太大,-x 2-x 3 通常夠用了
  • 用完及時停掉相關命令
  • 在線上高峰期操作要更謹慎

說直白點:

Arthas 是手術刀,不是電鋸。

你是去定位問題的,不是去給線上服務做行為實驗的。


七、新手最容易踩的幾個坑

1. 方法名寫對了,結(jié)果就是沒輸出

可能原因:

  • 類名沒寫全
  • 方法簽名沒匹配上
  • 目標方法根本沒被調(diào)用
  • 你 attach 錯進程了

別笑,這個問題發(fā)生頻率相當高。很多時候不是 Arthas 不工作,是人工作得比較有想象力。


2. 輸出太多,把自己看暈了

這是 watch、trace 常見問題。

建議從最小范圍開始,先看一兩個請求,再逐步擴大,不要一開始就讓終端進入“瀑布模式”。

如果你看到輸出瘋狂滾動,心里開始發(fā)虛,通常說明你觀察得太猛了。


3. 只盯技術指標,不結(jié)合業(yè)務判斷

Arthas 能告訴你“發(fā)生了什么”,但不一定直接告訴你“為什么業(yè)務會這樣”。

比如你看到一個方法耗時高,不代表它一定有 bug;也可能是這個請求本來就需要查很多數(shù)據(jù)。

所以排查時一定要結(jié)合:

  • 請求場景
  • 業(yè)務入?yún)?/li>
  • 調(diào)用鏈上下文
  • 近期發(fā)布記錄

工具負責給證據(jù),人負責做判斷。
別把工具當算命先生。


八、給一份夠用的排障套路

如果你現(xiàn)在只想先記住一套“線上排障起手式”,可以記這個:

  1. 進入 Arthas,確認進程
  2. dashboard 看整體狀態(tài)
  3. thread 看線程和 CPU
  4. scsm、jad 確認類和方法沒找錯
  5. trace 找耗時點
  6. watch 看參數(shù)、返回值、異常
  7. 遇到偶發(fā)問題,用 tt 留現(xiàn)場

這套不一定覆蓋所有復雜場景,但處理日常線上問題,已經(jīng)相當能打。


九、最后總結(jié)

Arthas 真正厲害的地方,不是命令多,也不是界面酷,而是它讓線上問題從“靠猜”變成“可觀察”。

以前很多排障過程像這樣:

  • 我感覺是這里有問題
  • 我猜可能是緩存
  • 我懷疑是線程池
  • 我覺得數(shù)據(jù)庫有點可疑

用了 Arthas 以后,風格會逐漸變成:

  • 參數(shù)就是這樣傳進來的
  • 這層調(diào)用耗時最高
  • 這個線程確實在忙這個方法
  • 線上跑的代碼就是這個版本

這就是區(qū)別。

它不會替你解決所有問題,但能讓你少走很多彎路。
對于 Java 開發(fā)來說,Arthas 非常值得熟悉,尤其是做線上排障、性能分析、問題定位的時候,幾乎屬于“會了不一定天天用,但真出事時會非常想它”。

如果要用一句大白話收尾,那就是:

線上出問題時,別急著拍腦袋,先讓 Arthas 說話。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容