记录一次CPU占用过高的排查解决过程

本文介绍了一种排查阿里云服务器上高CPU占用率的方法,包括使用top、ps、jstack等工具定位问题线程,最终确定是由于tomcat加载不必要的资源导致CPU占用率过高。

       最近部署在阿里云的项目总是无故被kill,并且登录到阿里云服务器查看的时候,发现卡的不行,怀疑可能cpu占用过高,就排查了一下,将排查过程进行记录。

1、先用top查看占用cpu较高的进程id(PID)

可以发现进程id为14073的进程一直占用98%的CPU 

2、查看该进程中线程详细情况,ps -mp 进程ID -o THREAD,tid,time

tid:线程id,time:该线程已经运行的时间 

可以发现,线程id为14181的线程CPU占有率比较高,而且运行了24分钟。

3、将tid转换成16进制的,等会可以在线程14073中通过转换后的数字查找该线程的详细信息

4、使用jstack 进程id|grep tid转换成16进制后的数字,查看该线程是否改在运行,可以看出该线程一会处于运行状态,一会处于waiting或者time_waiting状态。 

 5、使用jstack pid,查看该进程中线程的详细信息,可以看到有的时候3765处于RUNNABLE状态,有的时候处于TIME_WAITING状态,我们需要查看的是处于运行状态的详细信息,这样才能分析。

还可以使用jstack -l pid >> xxx.dump生成线程的快照信息,然后用visualVM进行分析。

 6、根据提示可以看到,占用CPU较高的是ContainerBackgroundProcessor线程,经查询,该线程是tomcat容器的后台线程(ContainerBackgroundProcessor),根据页面的提示,我猜测是tomcat加载资源的问题。因为这个tomcat是我从其它地方直接拷贝过来的,我就怀疑是拷贝的时候里面遗留别的项目的lib,所以启动项目时也会加载那些额外的资源。因此,我重新下载一个tomcat,然后安装,打包,启动。发现cpu果然降下来了。

可以看到新安装的tomcat的其进程占用CPU较低,已经降下来了。 

注:如果碰到运行jstack以后提示Unable to open socket file: target process not responding or HotSpot VM not loaded那就可能是你程序运行的用户和你当前的用户不是一个用户导致无法访问,可切换至启动该线程的用户然后再运行jstack即可

原因分析:
jvm运行时会生成一个目录hsperfdata_$USER($USER是启动java进程的用户),在linux中默认是/tmp。目录下会有些pid文件,存放jvm进程信息。

jps、jstack等工具读取/tmp/hsperfdata_$USER下的pid文件获取连接信息。

在Linux系统下排查Java程序CPU使用率过问题,可按以下方法进行: ### 1. 定位CPU占用的进程 使用`top`命令查看系统中各个进程的CPU占用情况。执行`top`命令后,按`P`键可以按照CPU使用率从到低对进程进行排序,找到Java进程对应的`PID`(进程ID)。 ```bash top ``` ### 2. 定位CPU占用的线程 确定Java进程的`PID`后,使用`top -Hp <PID>`命令查看该进程下各个线程的CPU占用情况,同样按`P`键可按CPU使用率排序,记录CPU占用线程的`TID`(线程ID)。 ```bash top -Hp <PID> ``` ### 3. 将线程ID转换为16进制 因为Java的线程栈信息中线程ID是16进制显示的,所以需要将上一步获取的`TID`转换为16进制。可以使用以下命令进行转换: ```bash printf "%x\n" <TID> ``` ### 4. 生成Java线程栈信息 使用`jstack`命令生成Java进程的线程栈信息,将输出重定向到一个文件中,方便后续查看。 ```bash jstack <PID> > jstack.log ``` ### 5. 在线程栈信息中查找问题线程 使用上一步转换得到的16进制`TID`,在`jstack.log`文件中查找对应的线程栈信息,分析线程正在执行的代码,定位可能存在问题的代码段。可以使用以下命令进行查找: ```bash grep <16进制TID> jstack.log -A 30 ``` ### 6. 分析堆内存使用情况 使用`jstat`和`jmap`命令分析Java堆内存的使用情况,查看是否存在内存泄漏等问题。 - 使用`jstat`查看堆内存的使用统计信息: ```bash jstat -gc <PID> 1000 10 ``` 上述命令表示每1000毫秒输出一次堆内存的GC统计信息,共输出10次。 - 使用`jmap`生成堆转储文件: ```bash jmap -dump:format=b,file=heapdump.hprof <PID> ``` 生成的堆转储文件可以使用工具(如Eclipse Memory Analyzer)进行分析。 ### 7. 分析垃圾回收情况 使用`jstat -gcutil <PID> <interval> <count>`命令查看Java进程的垃圾回收情况,了解垃圾回收的频率和效率。 ```bash jstat -gcutil <PID> 1000 10 ``` 该命令每1000毫秒输出一次垃圾回收统计信息,共输出10次。 ### 8. 检查代码逻辑 结合线程栈信息和堆内存分析结果,检查Java代码逻辑,查看是否存在死循环、无限递归、锁竞争等问题。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值