写作目的
最近看牛客网发现了CPU 100% 怎么办这个问题,这个问题的重点是定位和解决,会用到Linux和java的的很多命令,所以写篇博客记录和总结一下。
CPU 100%复现
之前有一个1核的腾讯云服务器,正好就不用搞虚拟机了。
写一个死循环Service
@Service
public class Cpu100Service {
public void cpu100() {
int a = 10;
while (a < 100) {
System.out.println(LocalDateTime.now().toString());
}
}
}
在controller中调用该Service就复现了。
@Autowired
private Cpu100Service cpu100Service;
@GetMapping("/cpu100")
public Object getWhileList() {
cpu100Service.cpu100();
return 1;
}
在服务器上启动服务后调用死循环的接口,则CPU出现负载100%的情况

定位问题
定位高负载的进程服务
首先使用top命令确认服务器的具体情况,定位到高负载的进程服务,如下图所示,我发现PID为929的服务CPU那栏高达86%,初步定位到是这个PID为929服务有问题。
定位到具体的线程
通过上面我们可以定位的进程的ID为929,接下来我们要定位到该进程的哪个线程占用CPU比较高,使用如下命令,其中929为进程ID。
top -Hp 929
此时可以定位到是线程1141占用CPU比较高。
将线程号(1141)转为16进制(后面用)
printf '%x\n' 1141
定位线程调用栈
通过以下命令把定位的进程线程调用栈保存下来,其中929为进程ID
jstack 929 > 929.log
下图为929.log的部分信息,其中我们知道进程中线程号(十进制1141,十六进制475)占用CPU比较高,我们可以通过线程ID的十六进制定位到线程,然后根据调用栈定位信息,发现定位到我们自己写的代码,然后在捋一捋自己代码的逻辑就好。