記一次用arthas排查jvm中CPU佔用過高問題

2022-09-02 06:29:06

記一次使用arthas排查jvm中CPU佔用過高問題。這工具屌爆了 碾壓我目前使用的全部JVM工具。

安裝 小試

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar --repo-mirror aliyun --use-http

jar後面的引數也可以不加 加上只是為了下載速度更快

接下來arthas 控制檯中顯示了當前機器上jvm程序列表 輸入需要排查的jvm程序號即可進入監控命令模式

找出CPU的元凶

處理問題之前 先想想如何去找到問題的原因 這個是解決問題個人覺得最重要的一步。

當前的現狀是jvm啟動後 cpu直接飆升到80+%。而記憶體是正常的,可以認為大概率是某個執行緒佔用了計算資源 導致的。所以第一步需要先把佔用過高執行緒給揪出來。

這次使用arthas排查。也順便提一下以前記錄過用top -Hp的方法找出佔用資源的執行緒PID 方法 top -Hp方法參考

輸入命令 thread 檢視所有執行緒資訊 預設是按照cpu資源佔用排名的

可以看到當前執行緒lettuce-nioEventLoop-4-1 佔用cpu高達47.75。其實這個執行緒名稱已經能定位到具體某個方向的問題了,所以執行緒名稱的定義需要有意義 為了方便排查問題。

可以看出因為我們程式使用了lettuce做redis的使用者端,主要是使用了redis stream

StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
.batchSize(10) // 一次性最多拉取多少條訊息
.targetType(String.class) // 目標型別。統一使用 String
.executor(mqConsumerExecutor)
.pollTimeout(Duration.ZERO)//0不超時
.build();

.pollTimeout(Duration.ZERO)這一句改為 .pollTimeout(Duration.ofMillis(10))cpu就正常了。原因就是設定了永不超時 資源得不到釋放。改為指定時間超時後 程式一點問題都沒有了。

檢視執行緒棧的引數

可以直接使用thread pid 上圖佔用最高的id為22 則輸入 thread 22 能看到類似jstack的功能

"lettuce-nioEventLoop-4-1" Id=22 RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)

還有一個更好用的命令 -n引數能顯示top-n-threads 比上面一種更詳細

"lettuce-nioEventLoop-4-1" Id=22 cpuUsage=49.51% deltaTime=99ms time=392976ms RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)

可以看出使用arthas排除這類問題 比使用top -Hp方便太多。當然這只是它的一個小功能而已。

原文 https://peachyy.gitee.io/2022/08/31/jvm_cpu_arthas_check/
公眾號