前兩天上線一個(gè)springboot服務(wù)(docker容器部署),服務(wù)啟動成功后,cpu負(fù)載瞬間上來直接100%。這樣的表現(xiàn)顯然是程序某個(gè)地方有問題。
1.第一反應(yīng)就是某個(gè)地方的邏輯形成了死循環(huán)。當(dāng)時(shí)通過shell命令
top
顯示

可以得到的信息是pid是340,但是有一個(gè)疑問就是無法確定對應(yīng)的是哪個(gè)docker容器啟動的服務(wù)。
2.通過docker命令
docker stats
打印出每一個(gè)容器對應(yīng)的指標(biāo)參數(shù)。類似下面這種:
那么通過以上兩個(gè)命令,就可以定位到底是哪個(gè)docker容器所承載的服務(wù)導(dǎo)致了cpu負(fù)載100%了。
既然已經(jīng)定位到了具體哪個(gè)服務(wù)導(dǎo)致的問題,那么下一步就要定位具體是哪個(gè)線程導(dǎo)致的問題?
3.通過shell命令打印進(jìn)程下所有線程的占用情況
top -H -p340
其中340就是第一步獲得的pid--->340

查看cpu那一列,找到異常數(shù)據(jù)為100%的那一行,并記錄。
4.通過docker命令
docker exec -it {容器id} /bin/bash
進(jìn)入容器內(nèi)部。因?yàn)槭莟omcat容器,也就意味著安裝了JDK,那么可以使用jvm命令。
通過
jps
查看容器內(nèi)正在運(yùn)行的java服務(wù)。一般是只有一個(gè)服務(wù):
那么咱們就可以直接通過以下命令打印線程堆棧
jstack -l 1 > pid.dump
1就是指的當(dāng)前運(yùn)行java服務(wù)的pid。

(實(shí)際上【第三步】可以明確是“pool-4-thread-3”這個(gè)線程導(dǎo)致cpu負(fù)載100%)
看以上截圖可知,問題出在TagHeartbeatCheckThread這個(gè)類的第55行。
6.根據(jù)提示,查看代碼:
RfidDataCache這個(gè)是一個(gè)本地緩存,如果本地緩存為空,那么便會導(dǎo)致死循環(huán)。問題定位已經(jīng)完成。
7.根據(jù)上面一系列的操作及問題定位,已經(jīng)可以定位到問題產(chǎn)生的具體原因。想要解決這個(gè)問題,可以在判斷本地緩存為空的時(shí)候,讓線程睡眠2秒,降低cpu的負(fù)載;或者使用阻塞隊(duì)列的方式,讓線程等待直至本地緩存數(shù)據(jù)不為空。