cpu负载突刺问题排查

现象:

通过监控工具巡检自己的服务发现服务cpu load存在周期性变高的现象,如图:


image.png

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


image.png

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

提出问题

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

查找问题

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

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

1.io繁忙?
image.png

image.png

image.png

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

2.线程上下文切换频繁?

使用命令:pidstat -w -p


image.png

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

3.cpu繁忙导致??

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


image.png

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


image.png

当线程池满了以后,会默认使用kafka的主线程去进行业务处理,以上也验证了这一点;

解决法案

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

实践方案

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

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

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

你可能感兴趣的:(cpu负载突刺问题排查)