1. 程式人生 > 其它 >Docker 容器內分析 java程式佔用 cpu 高問題排查分析

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 佔用高的。