线上告警CPU使用率过高排查分析

本文主要列举了如下几种可能造成CPU过高的场景进行排查分析。

1、代码死循环

启动了两个线程(线程一定要起一个合适的名称,出了问题时方便排查),一个线程空循环,一个线程每500ms循环一次。

public class Test {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                
            }
        });
        t1.setName("t1 thread");
        t1.start();
        Thread t2 = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t2.setName("t2 thread");
        t2.start();
    }
}

丢到服务器运行,top命令查看cpu使用情况,发现pid为15661的java进程CPU使用率达到99.9%。

在这里插入图片描述

继续使用top -Hp 15661查看线程状况,发现是15671的线程占用了CPU。

在这里插入图片描述
接下来使用jstack 15661命令,输出虚拟机当前时刻线程快照信息,jstack输出中线程id是以16进制显示,用刚才找到的使用CPU最高的线程15671,转换为16进制后就是0x3d37,直接定位到就是名称为“t1 thread”的这个线程。

在这里插入图片描述

2、线程过多

启动1000个线程,每个线程每休眠10ms执行一次。

public class MoreThread {
    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            Thread t = new Thread(() -> {
                while (true) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.setName("number:" + i + ", thread");
            t.start();
        }
    }
}

排查方式和上一个一样
在这里插入图片描述
进程下有大量的线程
在这里插入图片描述

jstack查看,线程都处于sleep状态,cpu忙于调度这1000个线程,导致使用率过高。

在这里插入图片描述

3、频繁YGC,FullGC

配置堆内存为32m,main线程每1ms需要申请一个5m大小的内存空间,导致需要频繁的垃圾回收。
-Xms32m
-Xmx32m

public class MoreFullGC {
    public static void main(String[] args) throws InterruptedException {
        while (true) {
            Thread.sleep(1);
            byte[] b = new byte[1024 * 1024 * 5];
        }
    }
}

前面都是一样的排查方式

在这里插入图片描述

在这里插入图片描述
21180和21179分别对应16进制0x52bb、0x52bc,这次发现一个main线程,因为main线程在无限循环,还有一个是VM Thread,当看到这个线程时就差不多可以联想是GC的问题了。

在这里插入图片描述

通过jstat命令,看一下垃圾回收的情况。
jstat -gc 21178 1000 10,每1秒一次输出指定进程下虚拟机当前内存和垃圾收集状况,输出10次。

YGC和FGC,差不多每秒200次。

在这里插入图片描述

总结

当遇到CPU过高时,基本排查思路就是先通过top命令,确认是否是我们的java进程,如果是则根据进程ID,再找到进程中耗时较高的线程id,再通过jstack命令输出当前虚拟机栈的状况进行匹配(jstack线程id为16进制,需要转换匹配),排查具体的代码,如果发现线程是VM Thread线程,那就通过jstat命令确认垃圾回收情况,如果要排查FullGC较高的原因,一般可以通过jmap、mat等工具再进行分析。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值