前言
在互聯(lián)網(wǎng)行業(yè)中,高并發(fā)的業(yè)務(wù)為常態(tài)区端,作為一名Java高級工程師,線上問題的排查手段和技巧必須熟練卦洽,比如某電商團隊的某個應(yīng)用突然CPU超高江锨,導(dǎo)致報警短信和郵件滿天飛吃警,如果讓你來定位一個問題,并快速消除預(yù)警泳桦,你該怎么辦汤徽?其中一點就是如何定位CPU消耗過高的線程,以及如何找到線程正在干的事情灸撰。幫助我們快速的定位問題和分析問題谒府。
本文為日常工作中實戰(zhàn)性較強的一個問題分析和定位技能。閱讀完本文浮毯,你將擁有更高層次的問題分析和處理能力完疫。
如何定位CPU高的線程
大體過程如下:
1、用top -H -p <pid>命令找到CPU高的線程ID债蓝。
2壳鹤、用jstack <vmid>命令打印jvm線程堆棧信息。
3饰迹、將第1步拿到的線程ID轉(zhuǎn)換為16進制芳誓。(可以用命令 printf '%x\n' ID來輸出16進制)
4余舶、用轉(zhuǎn)換后的線程ID在線程堆棧信息中查找匹配的nid線程。
5锹淌、到此已經(jīng)找到線程匿值,以及線程棧的詳細信息÷赴冢可以根據(jù)這些信息來判斷應(yīng)用當(dāng)前正在干什么壞事了挟憔。
定位Java線程CPU消耗高的線程(top -H命令)
命令:pid為jvm進程號
top -H -p <pid>
作用:列出指定進程下線程的信息,會按CPU的使用占比從大到小排列烟号。
上圖中列分別代表的意思為:進程中的線程ID、用戶名汪拥、線程優(yōu)先級
列名 | 含義 |
---|---|
PID | 進程ID |
USER | linux用戶名 |
PR | 線程優(yōu)先級 |
NI | nice值达传。負值表示高優(yōu)先級,正值表示低優(yōu)先級 |
VIRT | 進程使用的虛擬內(nèi)存總量迫筑,單位kb趟大。VIRT=SWAP+RES |
RES | 進程使用的、未被換出的物理內(nèi)存大小铣焊,單位kb逊朽。RES=CODE+DATA |
SHR | 共享內(nèi)存大小,單位kb |
S | 進程狀態(tài)曲伊。 |
%CPU | 上次更新到現(xiàn)在的CPU時間占用百分比 |
%MEM | 進程使用的物理內(nèi)存百分比 |
TIME+ | 進程使用的CPU時間總計叽讳,格式:時:分:秒 |
COMMAND | 命令名/命令行 |
上面的幾個參數(shù)中,最關(guān)心的是PID坟募、USER岛蚤、%CPU信息。從上圖中可以看到CPU占比最高的排在第1位懈糯,線程ID位14153(十六進制為:3749)涤妒,這個線程就是我們想要的線程。
jstack命令
命令:pid為jvm進程號
作用:獲取JVM線程堆椬快照
jstack <pid>
在線程堆棧中提供如下的幾個信息:
1她紫、jvm內(nèi)部的線程ID(tid), 操作系統(tǒng)上對應(yīng)的線程ID(nid)
2、線程鎖的狀態(tài)屿储,以及線程棧的軌跡信息贿讹。
如上圖,線程JStack-Test對應(yīng)的操作系統(tǒng)上的線程ID為0x3749
nid=0x3749
拿到這個ID够掠,是不是有點高興民褂?有沒有發(fā)現(xiàn)這個ID就是上一步中用top命令得到的ID?
有了線程堆棧信息,就能夠根據(jù)線程棧軌跡赊堪、線程的狀態(tài)來判斷是否有死鎖面殖,線程執(zhí)行的代碼是什么代碼。從而在這些信息的基礎(chǔ)上進一步幫助我們分析系統(tǒng)的瓶頸哭廉、線程死鎖畜普、CPU資源消耗等情況。
對于線程堆棧的分析群叶,將另起一篇文章來講解。
敬請期待6鄣础=至ⅰ!