Linux服務(wù)器如何快速定時CPU占用高的線程

場景描述

最近遇到一個生產(chǎn)環(huán)境,一個程序因為代碼寫的有問題,導(dǎo)致cpu占用很高,所以需要馬上排查問題,首先要先找出哪個程序,具體代碼在哪里,所以需要借助jstack、jmap這些命令來定位具體的線程,查看具體的線程信息

問題模擬

為了模擬生產(chǎn)環(huán)境問題,需要寫點代碼,讓ai寫吧,但是不要oom,只是讓cpu高就行,AI寫的代碼,接口傳一個比較大的值,比如10000

代碼語言:Javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController {    @GetMapping(value = "/test")    public void test(@RequestParam(value = "num", defaultValue = "10000")Integer num) {        // 定義線程數(shù)量,這里設(shè)置為CPU核心數(shù)的兩倍,以確保高CPU使用率        int numberOfThreads = Runtime.getRuntime().availableProcessors() * 2;        Thread[] threads = new Thread[numberOfThreads];        // 創(chuàng)建并啟動線程        for (int i = 0; i < numberOfThreads; i++) {            threads[i] = new Thread(new IntensiveTask(num));            threads[i].start();        }    }    static class IntensiveTask implements Runnable {        private Integer num = 10000;        public IntensiveTask(Integer num) {            this.num = num;        }        @Override        public void run() {            while (true) {                // 創(chuàng)建一個大型數(shù)組                int[] array = new int[num];                // 使用計算密集型操作,如排序                java.util.Arrays.sort(array);                // 短暫休眠以避免完全占用CPU                try {                    Thread.sleep(1);                } catch (InterruptedException e) {                    Thread.currentThread().interrupt();                    return;                }            }        }    }}

將代碼丟到開發(fā)環(huán)境,java啟動程序

代碼語言:JavaScript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

 nohup java -jar demo-0.0.1-SNAPSHOT.jar > /opt/logs/output.log 2>&1 &

調(diào)用接口:

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

curl http://127.0.0.1:8080/test?num=10000

問題處理

在window系統(tǒng)有任務(wù)管理器這些可視化界面可以看,在linux服務(wù)器也有,比如top命令

定位CPU占用高的進(jìn)程 在Linux服務(wù)器,可以使用top命令,其中%CPU表示cpu占用率,%MEM表示內(nèi)存占用率代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

top
Linux服務(wù)器如何快速定時CPU占用高的線程

直接使用top來看有時候不能很直觀,所以加點命令,

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

top -b -n 1 | head -n 16

-b選項表示批處理模式,-n 1表示只運(yùn)行一次top命令。head -n 16表示打印16行,這個行數(shù)根據(jù)具體情況加,因為我想打印出前10的進(jìn)程

Linux服務(wù)器如何快速定時CPU占用高的線程

想要持續(xù)監(jiān)控CPU和內(nèi)存占用最高的前10個進(jìn)程,加上watch命令,每1s會更新一次

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

watch -n 1 "top -b -n 1 | head -n 16"

也可以使用命令:

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

top -b -n 1 | head -n 20 | awk 'NR>1 {print $1, $2, $9, $10, $12}'
Linux服務(wù)器如何快速定時CPU占用高的線程

定位進(jìn)程中高CPU占用的線程 在前面的方法中使用top命令定位到進(jìn)程后,需要再定義進(jìn)程中具體的線程,可以使用命令,其中pid就是前面定位到的進(jìn)程ID代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

top -Hp pid

比如前面定位到2540這個進(jìn)程,監(jiān)控一下進(jìn)程下面具體的線程,發(fā)現(xiàn)線程2568、2569比較占cpu

Linux服務(wù)器如何快速定時CPU占用高的線程

嫌棄不夠直觀,直接打印一下前10,2540是進(jìn)程ID

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

ps -mp 2540 -o THREAD,tid | gawk 'NR!=1 && NR!=2 { printf "%s %xn",$2,$8 }' | sort -rn | head -10
Linux服務(wù)器如何快速定時CPU占用高的線程

將線程ID轉(zhuǎn)換為十六進(jìn)制 將前面的線程ID轉(zhuǎn)為十六進(jìn)制代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

printf "%xn" 2569
Linux服務(wù)器如何快速定時CPU占用高的線程

獲取線程堆棧信息代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

jstack 2540 | grep "a09" -A 30

通過線程堆棧信息就可以定位到具體的代碼

Linux服務(wù)器如何快速定時CPU占用高的線程

找到具體問題代碼,原來寫了個while(true)循環(huán)

Linux服務(wù)器如何快速定時CPU占用高的線程

監(jiān)控GC情況 當(dāng)然生產(chǎn)環(huán)境的問題不一定這么容易定位,所以需要監(jiān)控gc情況,使用jstat -gcutil 命令查看GC持續(xù)變化情況,如果發(fā)現(xiàn)Full GC次數(shù)過多,可能需要進(jìn)一步分析內(nèi)存使用情況

Linux服務(wù)器如何快速定時CPU占用高的線程

導(dǎo)出堆內(nèi)存文件 如果出現(xiàn)頻繁Full GC的問題,使用命令導(dǎo)出堆內(nèi)存文件:代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

jmap -dump:format=b,file=heapdump.hprof pid

分析堆內(nèi)存文件 使用MAT工具打開導(dǎo)出的heapdump.hprof文件,分析內(nèi)存泄漏和內(nèi)存分配情況,找出占用大量內(nèi)存的對象 優(yōu)化代碼

根據(jù)MAT的分析結(jié)果,定位代碼中的問題,優(yōu)化代碼

監(jiān)控生產(chǎn)環(huán)境

重新部署修改后的代碼,并使用top命令監(jiān)控CPU占用情況,確保問題得到解決,同時可以部署一下監(jiān)控平臺,比如zabbix等對生產(chǎn)環(huán)境服務(wù)器進(jìn)行監(jiān)控,及時發(fā)現(xiàn)問題

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊15 分享