线上CPU飚高(死循环,死锁...)?帮你迅速定位代码位置
Posted Hollis
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线上CPU飚高(死循环,死锁...)?帮你迅速定位代码位置相关的知识,希望对你有一定的参考价值。
top基本使用
第一行:基本信息
第二行:任务信息
第三行:CPU使用情况
第四行:物理内存使用情况
buff/cache:
buffers 和 cache 都是内存中存放的数据,不同的是,buffers 存放的是准备写入磁盘的数据,而 cache 存放的是从磁盘中读取的数据
在Linux系统中,有一个守护进程(daemon)会定期把buffers中的数据写入的磁盘,也可以使用 sync 命令手动把buffers中的数据写入磁盘。使用buffers可以把分散的 I/O 操作集中起来,减少了磁盘寻道的时间和磁盘碎片。
cache是Linux把读取频率高的数据,放到内存中,减少I/O。Linux中cache没有固定大小,根据使用情况自动增加或删除。
第五行:交换区使用情况
Swap(内存交换区):
是硬盘上的一块空间。在内存不足的情况下,操作系统把内存中不用的数据存到硬盘的交换区,腾出内存来让别的程序运行。因此,开启swap会一定程度的引起 I/O 性能下降(阿里服务器默认不开)
第六行:进程详细信息
死循环
构造的代码如下:
@RestController
@RequestMapping("top")
public class ShowTopController {
private Object lock1 = new Object();
private Object lock2 = new Object();
@RequestMapping("test")
public String test() {
return "success";
}
@RequestMapping("loop")
public String loop() {
System.out.println("start");
while (true) {}
}
@RequestMapping("deadlock")
public String deadlock() {
new Thread(() -> {
synchronized (lock1) {
try{
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {}
synchronized (lock2) {
System.out.println("thread1 over");
}
}
}).start();
new Thread(() -> {
synchronized (lock2) {
try{
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {}
synchronized (lock1) {
System.out.println("thread2 over");
}
}
}).start();
return "success";
}
}
参数选项名称
含义
p
通过指定进程ID(PID)来仅仅监控某个进程的状态。可以指定多个,-pN1 -pN2 … (-p N1 -p N2…也可)或者 -pN1,N2,N3 …(-p N1,N2…也可)
H
显示所有线程的运行状态指标。如果没有该参数,会显示一个进程中所有线程的总和。在运行过程中,可以通过H命令进行交互控制
先手动制造CPU飙高的场景,多执行几次,小编这里执行3次
curl localhost:8080/top/loop
执行top
jstack命令工具可以得到线程堆栈信息,根据这些线程堆栈信息,我们可以去检查Java程序出现的问题
看到pid为23757的进程CPU占用较高,执行如下命令
jstack 23757 > loop.txt
看看pid为23757的进程中线程的具体情况
top -p 23757 -H
当然你也可以使用交互命令
top -p 23757
然后再输入H,效果和上面一样
可以看到PID为23772,23773和23774的线程占用CPU较高
这里可能有人有疑惑,为什么线程也有PID啊?其实线程进程都会有自己的ID,这个ID就叫做PID,PID是不特指进程ID,线程ID也可以叫做PID
将10进制的23772转为16进制,因为jstack中PID用的是16进制
printf "%x" 23772
输出5cdc
打开loop.txt文件,搜5cdc
可以看到线程一直在执行ShowTopController中的第23行,即
while (true) {}
好了定位到代码中的位置了,当然生产环境中肯定不会写一个死循环的,有可能在特殊场景下出现死循环,或执行一个方法特别慢,用这种方法很快就能找到代码位置。
死锁
curl localhost:8080/top/loop
jstack 23757 > loop.txt
看到发现一个死锁,死锁代码的位置描述的很清楚,生产环境发生的死锁当然没有这么简单,所有学会用这些命令排查还是很有必要的
在GitHub更新中,欢迎关注,欢迎star。
直面Java第206期:什么是正则表达式
成神之路第015期:深入学习Java中的IO
深入并发第006期:Java线程池的正确使用姿势
- MORE | 更多精彩文章 -
如果你喜欢本文。
请长按二维码,关注Hollis
以上是关于线上CPU飚高(死循环,死锁...)?帮你迅速定位代码位置的主要内容,如果未能解决你的问题,请参考以下文章