Docker 容器內分析 java程式佔用 cpu 高問題排查分析
作者: 張首富
時間:2021-07-08
wx: y18163201
背景描述
我們目前所有的 java 服務都是封裝在 docker 裡面的,今天做壓力容量測試的時候發現有個服務佔用cpu 300%
,想找到是這個 java 程式的那個執行緒造成的問題,把問題反饋給開發讓他們去修復。
下面所使用的容器映象都是通過:Docker容器內執行 jvm 分析工具命令 文章內的打包方式構建的;如果你發現你的 jvm 引數不能使用,那麼建議你參考我的 dockerfile 進行構建
分析過程
通過監控發現 A 服務佔用 cpu 過高;(prometheus+grafana+cadvisor構建的監控)
等到宿主機上使用 top 判斷是否真的是這個容器造成的 CPU 高
top
進入互動模式 按鍵盤 c 是按照 CPU 使用率進行排序
確定是此服務沒有跑了。那麼開始分析是這個程序的那些執行緒出現的問題;因為我們服務都是封裝在容器裡,namespaces 和屬主機上是隔離的,所以我們到容器裡面去分析
docker exec -it A sh
apk add openjdk8 //安裝 jvm 分析工具
apk add htop // 安裝 htop 我們能更加清楚的看到是哪個執行緒佔用 cpu 高,不需要藉助其他命令;
進到 docker 容器內執行命令htop
進去到 htop 頁面按shift+p
按照 CPU 使用率排序。
找到 cpu 使用率前幾的執行緒號。記錄下來
使用dk自帶命令jstack獲取此時的執行緒快照並輸入到檔案中: jstack -l > ./jstack_result.txt 命令(為Java程序的id號)來獲取執行緒快照結果並輸入到指定檔案。
jstack -l 7 > 1.txt
使用 printf "%x\n" 命令(tid指執行緒的id號)將以上10進位制的執行緒號轉換為16進位制:
/home/work # printf "%x\n" 162 a2 /home/work # printf "%x\n" 163 a3 /home/work # printf "%x\n" 169 a9 /home/work # printf "%x\n" 164 a4
轉換後的結果分別為a2,a3,由於16進位制以0x開頭,所以對應的16進位制的執行緒號為0xa2和0xa3。
我們在剛才生成的執行緒快照中找 nid=0xa2,nid=0xa3 的執行緒
然後把這些提供給開發讓開發去檢視程式碼。
到此 docker 容器內分析 java cpu 使用率高的問題排查完成,
補充
在屬主機上可以使用 top -Hp PID 來找執行緒使用 cpu 佔用高的。