今天在查看项目服务器的时候,发现cpu一直占用99%多,于是就有了这篇文章。。。
1、找到占用cpu高的进程
通过top命令来查看cpu占用高的进程有哪些,如图:
top
这里的pid代表的就是进程id
2、查看当前进程内占用cpu的线程
通过命令来查到线程的id,如下:
//这里的2970就是第一步查到的占用cpu高的进程id,大写H小写p
top -H -p 2970
这里的pid代表着线程id
3、使用jstack命令来查看堆栈信息
需要注意几点:
- 登录用户必须是当前服务的用户
- 线程id需要转换为16进制
使用命令如下:
// 2970是进程id,f05是线程id3845的十六进制表示
jstack 2970 |grep f05 -A 30
看看第一个就是占用cpu的罪魁祸首:
com.midea.cdp.microservice.sdk.quene.SdkQueneManager
4、在项目里进行优化
-
问题:
我在项目里找见了这个类:很明显里面有一个死循环,一定是他的原因,但是这个包不在项目里,而是用的二方库的包,也就是说这个代码我根本没办法修改。public class SdkQueneManager implements Runnable, ApplicationListener<ContextRefreshedEvent> { private static final Logger log = LoggerFactory.getLogger(SdkQueneManager.class); @Resource( name = "link_quene" ) private BlockingQueue<SdkResult> bq; private IProjectAgentUdpService agentService; public SdkQueneManager() { } public void produce(SdkResult sr) throws InterruptedException { this.bq.put(sr); } public SdkResult consume() throws InterruptedException { return (SdkResult)this.bq.take(); } public void run() { // 可以看到这里写了一个死循环 while(true) { if (!this.bq.isEmpty()) { SdkResult sr = null; try { sr = this.consume(); } catch (InterruptedException var3) { var3.printStackTrace(); log.error(var3.getMessage(), var3); } this.agentService.submitResultQuene(sr); } } } public void onApplicationEvent(ContextRefreshedEvent event) { if (event.getApplicationContext().getParent() == null) { Thread t = new Thread(this); t.start(); } } public void setAgentService(IProjectAgentUdpService agentService) { this.agentService = agentService; } }
-
解决:
既然不能修改,那我们利用类加载机制的双亲委派原理,在项目里创建一个一模一样的包和类,然后把死循环那一段注释调。通过尝试确实可以,问题得以解决。