有时候发现,在Linux系统上运行java服务时,CPU占用率将近100%,长时间居高不下,这就需要好好排查一下了。
排查的大致方法步骤
1、top :命令定位应用进程 pid
2、top -Hp [pid] :定位应用进程对应的线程 tid
3、printf “%x\n” [tid] :将tid转换为十六进制
4、jstack [pid] | grep -A 10 [tid的十六进制] :打印堆栈信息
5、根据堆栈信息分析问题
示例代码
写个测试代码,打包上传到服务器,启动服务。
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/test/{count}")
public long testFun(@PathVariable("count") long count) {
long num = 0;
for (int i = 0; i < count; i++) {
num++;
}
return num;
}
}
调用接口:curl http://localhost:9999/api/cpu/10000000000
,然后服务器的CPU一会时间就飙到了100%。
接下来进行排查:
1、先找到最消耗CPU的进程的pid
// 执行 top 命令
> top
可以看到pid为 11167 的进程占用CPU是最高的,直接100%。
2、找到最消耗CPU的线程tid
// 执行 top -Hp [pid] 定位进程对应的线程 tid
> top -Hp 11167
可以看到tid为 11196的线程占用CPU是最高的,达到99.9%。
3、将线程pid转化为16进制格式
// printf "%x\n" [tid] :将tid转换为十六进制格式
> printf "%x\n" 11196
2bbc
4、查看线程的堆栈信息
// jstack [pid] | grep -A 10 [tid的十六进制] : 打印堆栈信息
> jstack 11167 | grep -A 10 2bbc
发现原来是 TestController 的testFun函数的问题。
5、根据堆栈信息分析问题
找到了源代码定位到了。