Linux之模拟CPU占用率过高故障排查

最近更新于2021.11.30

有时候我们可能会遇到CPU一直占用过高的情况。之前我的做法是,直接查找到相关的进程,然后杀死或重启即可。这个方法对于一般的应用问题还不大,但是要是是重要的环境的话,可万万使不得。

如果是重要的环境,那么我们就需要进行更加精确的定位。

下面我们来模拟JAVA进程占用CPU过高场景并讲一下如何排查CPU占用过高问题。

一、首先我们在Centos7上模拟消耗CPU资源的JAVA进程

首先配置好JDK环境,使命令行可以直接识别到java、javac命令。

(1)新建TestCpu.java文件,内容如下

public class TestCpu{
    public static void main(String[] args){
        while(true){
        }
    }
}

解释:代码里有个while(true){},形成无限循环,将直接导致CPU使用率飙升100%。注意文件命名TestCpu.java要和文件里类命名TestCpu保持一致。

(2)执行javac TestCpu.java进行编译

编译完成后会生成TestCpu.class文件

 (3)执行java TestCpu运行JAVA程序

二、获取占用CPU最多的进程pid

新开终端执行top命令(或者top -c,-c选项用来显示具体命令)查看CPU使用率
PS:CPU负载多少是正常?
个人认为是load average三个值(分别为1、5、15分钟负载)相差不大,说明系统负载平稳,具体是负载正常还是负载高,对于单核CPU,这三个值不大于1,说明负载有点吃紧,如果持续其中某个值大于1,则说明该时间段的负载高;对于多核CPU,这三个值分别除以CPU总逻辑核数,均不大于1,则负载平稳且不高,反之,则说明CPU吃紧

 三、进程这个范围还是太大了,我们需要具体到线程pid。(线程是进程的单位,一个进程是由若干线程组成)。

执行命令top -Hp 2757

三、获取线程十六进制pid

执行printf "%x\n" 2758

 为什么要转换成十六进制pid?因为我们后面要用到jstack。

jstack <PID>命令将当时Java应用程序的线程堆栈dump出来,而jstack记录的线程ID是16进制,故需要将top命令展示的线程号转换为16进制。

 四、通过jstack定位问题代码

jstack -- Prints Java thread stack traces for a Java process, core file, or remote debug server。

执行jstack 2757|grep -A 30 ac6

grep -A 30是为了显示(上下文,也就是上下行)下文30条相关的语句

可以看到,标红的部分有问题,回过头来看我们的TestCpu.java文件内容

 是不是刚好对应TestCpu程序main函数里的第三行,就是这里导致的CPU使用率飙升,是不是就符合我们刚开始使用while(true){}模拟消耗CPU资源的目标符合了。

好了,上面就是如何排查JAVA进程占用CPU高问题过程。
有人可能就想说了,既然是进程,那肯定要分java进程和非java进程,所以问题来了,非java进程,又该如何处理?
这个我暂时也没研究出来。。不过可以通过top命令,看占用CPU高的进程,是占用sy内核多还是占用us用户态多。Linux 操作系统有很多用来跟踪程序行为的工具,内核态的函数调用跟踪用「strace」,用户态的函数调用跟踪用「ltrace」,ltrace跟踪进程调用库函数。以strace为例
strace -cp <PID>
-c选项用来汇总各个操作的总耗时
如图:

 

 很明显,我们能看到 CPU 主要被 clone 操作消耗了,还可以单独跟踪一下 clone:
strace -T -e clone -p
通过「T」选项可以获取操作实际消耗的时间,通过「e」选项可以跟踪某个操作
所以到这里,我们继续定位程序里哪里用到clone函数就能知道原因了。类似的还有lstrace命令用于查看用户态函数。
这里可能说地比较简单,大家可以参考下
https://www.cnblogs.com/kongzhongqijing/articles/4913192.html

posted on   标配的小号  阅读(14419)  评论(1编辑  收藏  举报

努力加载评论中...

导航

点击右上角即可分享
微信分享提示