歡迎關注頭條號:老顧聊技術
精品原創技術分享,知識的組裝工
前言
在我們開發過程中,無法避免的會出現所謂的垃圾代碼,導致服務器的CPU一直處於100%。但我們應用已經上線,導致服務器CPU居高,但又不知道哪邊出現的問題,我們應該怎麼去找出哪邊的代碼出現問題呢?今天老顧就介紹幾種工具去快速定位。
演示代碼
我們先來編寫一下代碼,新建springboot的maven項目,創建web服務,引入SpringBoot內置web容器,pom.xml關鍵引用jar包如下:
<code><
dependency
><
groupId
>org.springframework.boot
groupId
><
artifactId
>spring-boot-starter-webartifactId
>dependency
>/<code>
創建service:TestWhile
![利用阿里開源工具進行排查線上CPU居高問題](http://p2.ttnews.xyz/loading.gif)
創建Controller:TestWhile
![利用阿里開源工具進行排查線上CPU居高問題](http://p2.ttnews.xyz/loading.gif)
配置文件application.properties
<code>server.port
=80
server.servlet.context-path
=/api/<code>
打包項目,上傳測試服務器
<code>java
-jar
demo-0
.0
.1-SNAPSHOT
.jar
&/<code>
打開瀏覽器,訪問死循環方法
打開瀏覽器,地址欄輸入http://xxxx/api/user/testWhile?size=2
返回“Hello 程序執行完畢”,說明調用成功。(開啟了2個死循環)
到此問題代碼,已經在服務器上面跑了。我們發現服務器報警,於是去線上排查。
原生方法
此方法無需額外安裝工具,在沒法連接互聯網的情況下使用此方法排查效果較好。
top、printf都是Linux原生命令,jstack、jstat是jdk自帶命令工具。
很多功能強大的Linux和java診斷工具也是以top、jstack、jstat為基礎命令做的封裝。
注意:jstack、jstat等命令需要jdk完整安裝,linux自帶的openJdk一般無此工具,可以在java的bin目錄下查看是否有這些命令。
找到最耗CPU的進程
命令:top –c,顯示進程運行信息列表
實例:top -c。
交互1:按1,數字1,顯示多核CPU信息。
交互2:鍵入P (大寫p),進程按照CPU使用率排序
我們看出了雙核CPU使用率已經達到100%。
而第一個進程PID是373的就是我們要找的罪魁禍首了;可以看到進程最後一列,COMMAND註釋的進程名:“java -jar demo-0.0.1-SNAPSHOT.jar”。
找到最耗CPU的線程
命令:top -H -p 【PID】,顯示一個進程的線程運行信息列表
實例:top -Hp 373 ,如下圖所示,可以看到多個高耗CPU使用率的線程
轉換線程PID為16進制
命令:printf “%x\n” 【線程pid】,轉換多個線程數字為十六進制,第4步使用時前面加0x。
實例:printf '%x\n' 406 405 375 376,得到結果196、195、177、178 ;如下圖所示:
查看堆棧,定位線程
命令:jstack 【進程PID】| grep 【線程轉換後十六進制】-A10 , 使用jstack獲取進程PID堆棧,利用grep定位線程id,打印後續10行信息。
實例:jstack 373 | grep '0x196' -A10,如下圖所示:
我們通過查看堆棧信息,發現了問題是TestWhile.whileTrue引起的;
而且發現有2個GC線程,看上圖中的“GC task thread#0 (ParallelGC)”,代表垃圾回收線程,該線程會負責進行垃圾回收
存儲堆棧,批量查看
查看堆棧信息,我們也可以換個方法查看,可以先將jstack堆棧信息存儲起來。
命令:jstack 【進程PID】> 【文件】
實例:jstack 373 > demo.dump,存儲373進程的堆棧信息。
再使用cat + grep查找看看後面幾個高CPU線程的堆棧信息。
實例:cat -n demo.dump | grep -A10 '0x196',如下圖所示:
可以看到線程0x196【線程196】產生堆棧信息,直指方法whileTrue。
GC查看
我們看到上圖中有4個線程中的2個線程沒有看到java代碼,而是GC task thread#0 (ParallelGC),這個是GC垃圾回收的線程,是不是死循環導致了GC太頻繁,導致CPU使用率居高不下呢?
我們使用jstat看下jvm的GC信息看看。
命令:jstat -gcutil 【進程PID】【毫秒】【打印次數】
實例:jstat -gcutil 373 2000 5,查看373進程的GC信息,每2秒打印一次,共打印5次,如下圖所示:
S0:倖存1區當前使用比例
S1:倖存2區當前使用比例
E:伊甸園區使用比例
O:老年代使用比例
M:元數據區使用比例
CCS:壓縮使用比例
YGC:年輕代垃圾回收次數
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間
GCT:垃圾回收消耗總時間
上面的原生方法查找要遵循一定的步驟,相對有些麻煩點,有沒有比較簡單的方法呢?往下看
Arthas(阿爾薩斯)
Arthas(阿爾薩斯)是阿里巴巴開源出來的一個針對 java 的線上診斷工具,功能非常強大。Arthas 支持JDK 6+,支持Linux/Mac/Windows,採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。我們來看看
下載Arthas
使用arthas-boot(推薦)
下載arthas-boot.jar,然後用java -jar的方式啟動:
<code>curl
-O https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar/<code>
按1進入java進程,此時java進程PID已經變成373
進入阿爾薩斯完成,如下圖,可以看到登錄路徑已經變成了[arthas@17376]$,可以輸入dashboard,進入監控頁面了。
監控查看
已經進入Arthas操作界面,輸入dashboard,回車後將看到線程及堆棧信息,如圖所示,arthas已經將cpu高使用率的線程給安排上了。
上面我們就看到有2個線程居高不下,還有GC的數量和耗時。
thread【ID】查看線程
ctrl + c 退出dashboard界面,輸入thread 32查看線程信息,如下圖所示:
可以看到是TestWhile類中的whileTrue方法中的put方法導致cpu使用率升高。
問題一下子就出來了,Arthas功能不單單止於此,可以直接反編譯,看看代碼。
jad反編譯
使用Arthas自帶的反編譯方法jad,輸入命令:
jad com.rainbow.demo.service.TestWhile
可以反編譯java的class查看問題函數的具體代碼,如下圖所示:
退出arthas
最後,既然問題已經找到,那就退出Arthas吧。輸入命令:quit
Arthas的功能是非常強大的,這裡就簡單介紹,下一次老顧用專門的文章介紹
老顧在介紹一個更簡單的一個腳本,立刻發現問題所在
show-busy-java-threads
show-busy-java-threads.sh這個工具是useful-scripts工具集的其中一個工具。
show-busy-java-threads用於快速排查Java的CPU性能問題(top us值過高),自動查出運行的Java進程中消耗CPU多的線程,並打印出其線程棧,從而確定導致性能問題的方法調用。
注意:此工具的核心還是使用jdk的jstack方法,只是在其上做了封裝展示。
# 下載到當前目錄下
下載地址:https://github.com/oldratlee/useful-scripts/releases
在bin下面有很多工具,我們這次只要show-busy-java-threads.sh
上傳show-busy-java-threads腳本到服務器
# 一定賦予執行權限
chmod +x show-busy-java-threads
直接運行
<code>./show
-busy-java
-threads /<code>
如下圖所示,找到了CPU使用率前5高的線程,查找非常迅速。
從前面兩個線程可以看出,與使用原生工具(jstack)看到的一樣。
其他命令
與Arthas一樣,show-busy-java-threads也有一些其他很好用的增強命令:
show-busy-java-threads
從所有的 Java進程中找出最消耗CPU的線程(缺省5個),打印出其線程棧。
show-busy-java-threads -c 3
-c 3:3為n,指定顯示最耗cpu使用率前3的線程。
show-busy-java-threads -c 3 -p 17376
展示進程17376耗費CPU組多的3個線程;
-p 17376 :17376為進程PID,-p參數指定進程PID。
show-busy-java-threads -s 【指定jstack命令的全路徑】
對於sudo方式的運行,JAVA_HOME環境變量不能傳遞給root,
而root用戶往往沒有配置JAVA_HOME且不方便配置,
顯式指定jstack命令的路徑就反而顯得更方便了
show-busy-java-threads -a yao.log
將輸出結果導入到指定文件yao.log中
show-busy-java-threads 3 5
每5秒執行一次,一共執行3次; 缺省執行一次,缺省間隔是3秒
總結
今天老顧介紹了3中方法排查服務器CPU負載過高的情況,主要流程是
1、查看CPU負載過高進程。
2、查看進程中負載高的線程。
3、獲取進程中的堆棧信息。
4、獲取堆棧中對應的線程信息,找到裡面的問題方法。
在排查過程中我們不只使用了原生工具,還使用了增強工具Arthas與show-busy-java-threads,大大簡化了我們排查的步驟。
其實增強工具無非就是在原生方法上面封裝了而已,有很多這種工具都是在原生方法中封裝而成。今天就介紹到這裡,謝謝!!!
---End---
專欄
微服務API網關框架
199幣
10人已購
老顧的微服務網關分享課程,請大家多多支持
推薦閱讀
b、企業級SpringBoot應用多個子項目配置文件規劃、多環境支持(一)
c、企業級SpringBoot應用多個子項目配置文件規劃、多環境支持(二)
d、企業級SpringBoot應用多個子項目配置文件之配置中心(三)
1、基於RocketMq的SpringCloud Stream框架實戰入門
2、如何搭建消息中間件應用框架之SpringCloud Stream
3、面試必備:網關異常了怎麼辦?如何做全局異常處理?
4、Gateway網關係列(二):SpringCloud Gateway入門實戰,路由規則
5、Gateway網關係列開篇:SpringCloud的官方網關Gateway介紹
6、API網關在微服務架構中的應用,這一篇就夠了
7、學習Lambda表達式看這篇就夠了,不會讓你失望的哦(續篇)
8、Lambda用在哪裡?幾種場景?
9、為什麼會出現Lambda表達式,你知道嗎?
10、不說“分佈式事務”理論,直接上大廠阿里的解決方案,絕對實用
11、女程序員問到這個問題,讓我思考了半天,Mysql的“三高”架構
12、大廠二面:CAP原則為什麼只能滿足其中兩項?而不能同時滿足
13、阿里P7二面:聊聊零拷貝的原理
14、秒殺系統的核心點都在這裡,快來取
15、你瞭解如何利用token方式實現分佈式Session嗎?
16、Mysql索引結構演變,為什麼最終會是那個結構呢?讓你一看就懂
17、一場比賽涉及到的知識,用通俗易通的方式介紹併發協調
18、企業實戰Redis全方面思考,你思考了嗎?
19、面試題:Thread的start和run的區別
20、面試題:什麼是CAS?CAS的作用以及缺點
21、如何訪問redis中的海量數據?避免事故產生
22、如何解決Redis熱點問題?以及如何發現熱點?
23、如何設計API接口,實現統一格式返回?
24、你真的知道在生產環境下如何部署tomcat嗎?
25、分享一線互聯網大廠分佈式唯一ID設計 之 snowflake方案
26、分享大廠分佈式唯一ID設計方案,快來圍觀
27、你想了解一線大廠的分佈式唯一ID生成方案嗎?
28、你知道如何處理大數據量嗎?(數據拆分篇)
29、如何永不遷移數據和避免熱點? 根據服務器指標分配數據量(揭秘篇)
30、你知道怎麼分庫分表嗎?如何做到永不遷移數據和避免熱點嗎?
31、你瞭解大型網站的頁面靜態化嗎?
32、你知道如何更新緩存嗎?如何保證緩存和數據庫雙寫一致性?
33、你知道怎麼解決DB讀寫分離,導致數據不一致問題嗎?
34、DB讀寫分離情況下,如何解決緩存和數據庫不一致性問題?
35、你真的知道怎麼使用緩存嗎?
36、如何利用鎖,防止緩存擊穿?重構思想的重要性
37、海量訂單產生的業務高峰期,如何避免消息的重複消費?
38、你知道如何保障生產端100%消息投遞成功嗎?
39、微服務下的分佈式session該如何管理?
40、阿里二面:filter、interceptor、aspect應如何選擇?很多人中招
41、互聯網架構重要組員CDN,很多高級開發都沒有實操過,來看這裡
42、阿里二面:CDN緩存控制原理,看看能不能難住你
43、SpringCloud Alibaba之Nacos多環境多項目管理
44、SpringCloud Alibaba系列之Nacos配置中心玩法
45、SpringCloud Alibaba之Nacos註冊中心
46、SpringCloud Plus版本之SpringCloud Alibaba
47、SpringCloud Alibaba之Nacos集群、持久化
48、SpringCloud Alibaba之Nacos共享配置、灰度配置
49、SpringCloud Alibaba之Sentinel工作原理
50、SpringCloud Alibaba之Sentinel流控管理
51、SpringCloud Alibaba之Sentinel降級管理
52、SpringCloud Alibaba之Sentinel熱點參數限流
53、SpringCloud Alibaba之Sentinel的API實戰