cpu负载突刺问题排查

如题所述

第1个回答  2022-07-25
通过监控工具巡检自己的服务发现服务cpu load存在周期性变高的现象,如图:

机器的cpu核数是4核,最高点明显超过了4,但是cpu使用率没有明显变高,如图:

cpu有突刺的现象是gc时引起的,这里先不做赘述;

那么是什么原因引起的cpu load变高呢???,又该如何解决呢?

一、引起load变高的原因有哪些:
1.磁盘io繁忙,网络io繁忙
2.线程上下文切换频繁
3.cpu繁忙

二、根据上面提出的三个原因去寻找解决方案

由上面三张图对比可以看出负载升高的时候,磁盘io以及网络io并没有任何变化还是保持和之前一样,说明不是io影响的。

使用命令:pidstat -w -p <pid>

由以图可以看出来,每秒自愿上下文切换(voluntary context switches)的次数为0(cswch );
被系统强制调度导致,每秒非自愿上下文切换(non voluntary context switches)的次数(nvcswch)的次数也为0;
说明不是线程频繁切换导致的

从最上面的cpu整体使用率看到并不是很高,那么应该不是cpu繁忙导致的;
继续向下排查,
pidstat查看java线程内详细信息,可发现用户态cpu使用率很高,长时间占用CPU,导致等待线程增多;

结合服务业务发现:
该服务是批量拉去kafka消息,然后使用线程池进行消费,而这个线程池使用的拒绝策略为CallerRunsPolicy,也就是当线程池执行不过来,并且阻塞队列也满的时候就会默认使用主线程来进行处理;
继续排查确认:
1.通过命令top -Hp pid 查看进程下最耗费cpu的线程
2.printf “%x\n” 得到线程的16进制
3.jstack 进程 |grep 线程id 获取线程状态
执行以上步骤的到文件,观察发现,最繁忙的线程就是kafka线程

1、减少一批消息的拉去数量,使当前线程池足够消费;
2、增大线程池数量的核心线程数(这种需要判断当前服务是io密集型还是cpu密集型,此方案选用)
3、更改业务逻辑,减少rpc,尽量减少业务处理,加快消费速度;
以上三种方式可以一起使用,也可以部分使用;

1.先减少批量拉取的消息数,观察load是否有降低;

2.因为我的业务服务是网络io密集型,所以我适当增大了业务线程池的核心线程数;

3.最后再来看业务逻辑层面是否存在优化的空间;
前两步结束后,负载已经降低到正常范围时,最后一步业务逻辑优化可选择性的去做;
相似回答