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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步