首先,先用放之四海而皆準(zhǔn)的命令 top,確認(rèn)一下是不是 Java 進(jìn)程是罪魁禍?zhǔn)住ava 進(jìn)程要不然就是個后臺任務(wù),要不然就是個 jar 包,比如一個Spring Boot 服務(wù)。
剛接觸開發(fā)那會兒,別的命令都不會,一看到CPU飆升,上來就是一個 top,當(dāng)top 命令執(zhí)行完了,也就完了。就像一個舉重選手用盡了所有力氣,然后就只能呆坐在哪里了。
下面介紹兩種后續(xù)操作,讓我們在執(zhí)行完 top以后,確定是 Java 進(jìn)程搞的鬼的情況下,順利的找出出現(xiàn)問題的方法。
第一種,用系統(tǒng)工具和 JDK 自帶的 jstack 工具。第二種,用 Arthas 探測工具。
使用 jstack 工具
第一步,使用 top 找到占用 CPU 最高的 Java 進(jìn)程
前面說了這一步,就是使用 Top 命令
使用 top命令發(fā)現(xiàn)占用 CPU 99.7% 的線程是 Java 進(jìn)程,進(jìn)程 PID 為 13731。
第二步,找到占用 CPU 最高的線程
上一步用 top命令找到了那個 Java 進(jìn)程。那一個進(jìn)程中有那么多線程,不可能所有線程都一直占著 CPU 不放,這一步要做的就是揪出這個罪魁禍?zhǔn)?,?dāng)然有可能不止一個。
接下來,還是用 top命令,只不過加一個參數(shù)-Hp ,就是下面這樣
top-Hppid
H參數(shù)表示要顯示線程級別的信息,p則表示指定的pid,也就是進(jìn)程id。代入前面得到的那個Java進(jìn)程,完整的命令是這樣的
top-Hp13731
執(zhí)行之后,這個Java進(jìn)程中占用線程占用 CPU 的情況就列出來了。
可以看到占用 CPU 最高的那個線程 PID 為 13756。
第三步,保存線程堆棧信息
這就要用到 JDK 默認(rèn)提供的一個工具了,叫做 jstack。當(dāng)你安裝了 JDK 之后,在 bin目錄下會有一大堆內(nèi)置的工具,java也是其中之一,還有另外我們可能比較熟悉的 javac
jstack 用于生成 Java 進(jìn)程的線程快照(thread dump)。線程快照是一個關(guān)于 Java 進(jìn)程中所有線程當(dāng)前狀態(tài)的快照,包括每個線程的堆棧信息。通過分析線程快照,可以了解 Java 進(jìn)程中各個線程的運(yùn)行狀態(tài)、鎖信息等。
我們用jstack的目的就是將那個占用 CPU 最高的線程的堆棧信息搞下來,然后進(jìn)一步分析。使用命令 jstack pid > out.log將某個進(jìn)程的堆棧信息輸出到 out.log文件中。
當(dāng)前 Java 程序的所有線程信息都可以通過 jstack命令查看,我們用jstack命令將第一步找到的 Java 進(jìn)程的線程棧保存下來。
jstack13731>thread_stack.log
第四步,在線程棧中查找最貴禍?zhǔn)椎木€程
第二步已經(jīng)找到了這個罪魁禍?zhǔn)椎木€程 PID 是 13756。
然后我們將 13756轉(zhuǎn)換為 16 進(jìn)制的,可以用在線進(jìn)制轉(zhuǎn)換的網(wǎng)站直接轉(zhuǎn)換,比如 https://tool.oschina.net/hexconvert 這個,轉(zhuǎn)換結(jié)果為 0x35bc。
最后,我們在線程棧中,也就是上一步保存的那個 thread_stack.log 文件,在里面查找這個16進(jìn)制的線程 id (0x35bc)。
然后,我么能看到了我們需要的線程名稱、線程狀態(tài),哪個方法的哪一行代碼消耗了最多的 CPU 都很清楚了。
第二種,Arthas
Arthas 是阿里開源的一款線上監(jiān)控診斷產(chǎn)品,通過全局視角實(shí)時查看應(yīng)用 load、內(nèi)存、gc、線程的狀態(tài)信息,并能在不修改應(yīng)用代碼的情況下,對業(yè)務(wù)問題進(jìn)行診斷,包括查看方法調(diào)用的出入?yún)?、異常,監(jiān)測方法執(zhí)行耗時,類加載信息等,大大提升線上問題排查效率。
用 Arthas 查找占用 CPU 最高的方法只是一個開胃小菜,除此之外,它最大的用途是在不改代碼、不重啟服務(wù)的情況下對程序進(jìn)行動態(tài)監(jiān)控。如果你碰到了線上詭異問題,一定要用 Arthas 嘗試找一找問題,開闊一下眼界。
好了,更多的功能到官網(wǎng) https://arthas.aliyun.com/ 了解吧,接下來就將一下如何用 Arthas 達(dá)到前面用 jstack 同樣的目的。
安裝 Arthas
當(dāng)然了,要使用 Arthas,你就必須先把它安裝到你的目標(biāo)服務(wù)器上,也就是那個出問題的Java服務(wù)所在的服務(wù)器。
下載 jar 包
curl-Ohttps://arthas.aliyun.com/arthas-boot.jar
啟動 Arthas 服務(wù)
java-jararthas-boot.jar
啟動之后,會列出當(dāng)前這臺服務(wù)器上的所有 Java 進(jìn)程,然后你選擇你要排查的那個服務(wù)即可。
然后出現(xiàn) arthas@之后表示已經(jīng)啟動,并成功 attach 到目標(biāo)進(jìn)程上 。
然后可以輸入命令 dashboard看一下實(shí)時面板,默認(rèn) 5 秒刷新一次,在這個面板上能夠看到線程、內(nèi)存堆棧、GC和Runtime的基本信息。如果你用過 VisualVM 的話,就和那個基本一樣。
好了,開始用 Arthas 找到導(dǎo)致 CPU 負(fù)載過高的問題吧。
找到占用CPU最高的進(jìn)程
第一步,其實(shí)還是用 top命令找到占用 CPU 最高的進(jìn)程,也就是 Arthas 啟動時選擇 attach 的那個 Java 進(jìn)程。
然后 java -jar arthas-boot.jar啟動Arthas,并attach 。
找到占用 CPU 最高的線程
執(zhí)行 thread命令,這個命令會顯示所有線程的信息,并且把CPU使用率高的線程排在前面。
這樣,一眼就看出來了,第一個線程的 CPU 使用率高達(dá) 99% 了,就是它。
查看堆棧信息
使用 thread ID 獲取堆棧信息,其實(shí)就是 jstack pid相同的作用。通過前一步看到這個線程的 ID 是18,然后執(zhí)行 thread 18
然后直接就看出來了出現(xiàn)問題的位置,TestController.java文件的 high方法的第23行。然后進(jìn)代碼看
com.moonkite.wallpapermanage.controller.TestController.high(TestController.java:23)
這個方法是我故意寫的死循環(huán),真實(shí)情況當(dāng)然沒有這么明顯,還需要針對具體代碼認(rèn)真分析。
總結(jié)
高 CPU 占用率這個問題是一種很常見也很典型的線上問題,排查方式只要按上述順序記下來就基本上沒什么問題。
其實(shí)還是推薦使用 Arthas,除了它確實(shí)功能非常多之外,還有就是在線上場景下,使用 jstack有時會碰到問題,如果這個線程已經(jīng)忙的一點(diǎn)轉(zhuǎn)圜的余地都沒有了,jstack命令可能會執(zhí)行失敗。
審核編輯:劉清
-
cpu
+關(guān)注
關(guān)注
68文章
10854瀏覽量
211574 -
JAVA
+關(guān)注
關(guān)注
19文章
2966瀏覽量
104701
原文標(biāo)題:面試官:CPU 100% 問題怎么排查?
文章出處:【微信號:小林coding,微信公眾號:小林coding】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論