最近遇到一个生产环境,一个程序因为代码写的有问题,导致CPU占用很高,所以需要马上排查问题,首先要先找出哪个程序,具体代码在哪里,所以需要借助jstack
、jmap
这些命令来定位具体的线程,查看具体的线程堆栈信息
为了模拟生产环境问题,需要写点代码,让AI写吧,但是不要oom,只是让cpu高就行,AI写的代码,接口传一个比较大的值,比如10000
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;
@RestController
public class HelloController {
@GetMapping(value = "/test")
public void test(@RequestParam(value = "num", defaultValue = "10000")Integer num) {
// 定义线程数量,这里设置为CPU核心数的两倍,以确保高CPU使用率
int numberOfThreads = Runtime.getRuntime().availableProcessors() * 2;
Thread[] threads = new Thread[numberOfThreads];
// 创建并启动线程
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) {
// 创建一个大型数组
int[] array = new int[num];
// 使用计算密集型操作,如排序
java.util.Arrays.sort(array);
// 短暂休眠以避免完全占用CPU
try {
Thread.sleep(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
}
将代码丢到开发环境,java启动程序
nohup java -jar demo-0.0.1-SNAPSHOT.jar > /opt/logs/output.log 2>&1 &
调用接口:
curl http://127.0.0.1:8080/test?num=10000
在window系统有任务管理器这些可视化界面可以看,在Linux服务器也有,比如top
命令
%CPU
表示cpu占用率,%MEM
表示内存占用率top
直接使用top
来看有时候不能很直观,所以加点命令,
top -b -n 1 | head -n 16
-b选项表示批处理模式,-n 1表示只运行一次top命令。head -n 16表示打印16行,这个行数根据具体情况加,因为我想打印出前10的进程
想要持续监控CPU和内存占用最高的前10个进程,加上watch
命令,每1s会更新一次
watch -n 1 "top -b -n 1 | head -n 16"
也可以使用命令:
top -b -n 1 | head -n 20 | awk 'NR>1 {print $1, $2, $9, $10, $12}'
top -Hp pid
比如前面定位到2540这个进程,监控一下进程下面具体的线程,发现线程2568、2569比较占cpu
嫌弃不够直观,直接打印一下前10,2540是进程ID
ps -mp 2540 -o THREAD,tid | gawk 'NR!=1 && NR!=2 { printf "%s %x\n",$2,$8 }' | sort -rn | head -10
printf "%x\n" 2569
jstack 2540 | grep "a09" -A 30
通过线程堆栈信息就可以定位到具体的代码
找到具体问题代码,原来写了个while(true)循环
jmap -dump:format=b,file=heapdump.hprof pid
根据MAT的分析结果,定位代码中的问题,优化代码
重新部署修改后的代码,并使用top命令监控CPU占用情况,确保问题得到解决,同时可以部署一下监控平台,比如zabbix等对生产环境服务器进行监控,及时发现问题