应用服务占用CPU过高情况排查

问题描述 (1)业务开发人员在启动项目时,会较高概率的出现cpu满载且一直无法停止的问题。任务管理器可以看到javaw.exe占用率为90%以上 (2)当启动项目时debug项目时,也会出现异常的卡顿,且能发现cpu占用率在稳步上升。 解决思路 1.尝试重现问题后,通过jvisualvm(jdk8中自带,后续版本被移除,但是可以兼容使用)工具观察堆、cpu运行的状态,能看出cpu是一直处于高负荷运行状态,且堆内存占用不大,GC线程也未占用cpu。可以判断是项目中部分线程一直在运行导致了cpu满载。 2.jps命令可以获取到当前运行的java进程号。通过比较cpu满载和jps列出的PID,可以确定满载的javaw.exe和Application为同一进程。

3.此时需要更进一步看到具体的线程占用情况,此时由于windows不能查看,需要下载对应的微软官方推荐的工具Process Explorer。

4.运行后选择对应的PID进程,右键点击选择Properties,可查看到对应的线程的TID。

5.在cpu发生满载现象时,执行命令jstack -l PID c:/*.stsck可获取到当前所有线程的状态。并在指定路径下生成了stack文件

6.此时获取到的TID为4位数字,通过win10自带的程序员计算器转换为16进制后在生成的stack文件中搜索线程即可。

7.此问题中定位到的线程如下,存在多个线程长期占用CPU且处于运行状态、

8.下面就是排查代码问题 发现当存在请求调用时,如果项目未启动则会导致此方法一直在自旋。 发生原因:

(1)由于liemsStarted变量未使用volatile关键字进行修饰,在多线程运行环境下,http线程并不能够及时的感知到此变量值已经改变。 (2)不加volatile会在编译时发生指令重排的优化,此代码可能会变成if(!liemsStarted){while(true){}}。 (3)while循环体中未执行任何代码,导致cpu无足够的间隔去重新获取liemsStarted的值,如果此处存在System.out.print,也可避免。 解决方案:

经验分享 程序员 微信小程序 职场和发展