前言
在互聯網行業中,高并發的業務為常態,作為一名Java高級工程師,線上問題的排查手段和技巧必須熟練,比如某電商團隊的某個應用突然CPU超高,導致報警短信和郵件滿天飛,如果讓你來定位一個問題,并快速消除預警,你該怎么辦?其中一點就是如何定位CPU消耗過高的線程,以及如何找到線程正在干的事情。幫助我們快速的定位問題和分析問題。
本文為日常工作中實戰性較強的一個問題分析和定位技能。閱讀完本文,你將擁有更高層次的問題分析和處理能力。
如何定位CPU高的線程
大體過程如下:
1、用top -H -p <pid>命令找到CPU高的線程ID。
2、用jstack <vmid>命令打印jvm線程堆棧信息。
3、將第1步拿到的線程ID轉換為16進制。(可以用命令 printf '%x\n' ID來輸出16進制)
4、用轉換后的線程ID在線程堆棧信息中查找匹配的nid線程。
5、到此已經找到線程,以及線程棧的詳細信息。可以根據這些信息來判斷應用當前正在干什么壞事了。
定位Java線程CPU消耗高的線程(top -H命令)
命令:pid為jvm進程號
top -H -p <pid>
作用:列出指定進程下線程的信息,會按CPU的使用占比從大到小排列。
上圖中列分別代表的意思為:進程中的線程ID、用戶名、線程優先級
列名 | 含義 |
---|---|
PID | 進程ID |
USER | linux用戶名 |
PR | 線程優先級 |
NI | nice值。負值表示高優先級,正值表示低優先級 |
VIRT | 進程使用的虛擬內存總量,單位kb。VIRT=SWAP+RES |
RES | 進程使用的、未被換出的物理內存大小,單位kb。RES=CODE+DATA |
SHR | 共享內存大小,單位kb |
S | 進程狀態。 |
%CPU | 上次更新到現在的CPU時間占用百分比 |
%MEM | 進程使用的物理內存百分比 |
TIME+ | 進程使用的CPU時間總計,格式:時:分:秒 |
COMMAND | 命令名/命令行 |
上面的幾個參數中,最關心的是PID、USER、%CPU信息。從上圖中可以看到CPU占比最高的排在第1位,線程ID位14153(十六進制為:3749),這個線程就是我們想要的線程。
jstack命令
命令:pid為jvm進程號
作用:獲取JVM線程堆棧快照
jstack <pid>
在線程堆棧中提供如下的幾個信息:
1、jvm內部的線程ID(tid), 操作系統上對應的線程ID(nid)
2、線程鎖的狀態,以及線程棧的軌跡信息。
如上圖,線程JStack-Test對應的操作系統上的線程ID為0x3749
nid=0x3749
拿到這個ID,是不是有點高興?有沒有發現這個ID就是上一步中用top命令得到的ID?
有了線程堆棧信息,就能夠根據線程棧軌跡、線程的狀態來判斷是否有死鎖,線程執行的代碼是什么代碼。從而在這些信息的基礎上進一步幫助我們分析系統的瓶頸、線程死鎖、CPU資源消耗等情況。
對于線程堆棧的分析,將另起一篇文章來講解。
敬請期待!!!