错误告知
今天收到阿里云的警告邮件,告知我的实例当前CPU
负载过高,当时就奇怪了,怎么实例负载过高了?于是登录的服务器查看当前CPU
以及系统负载情况,果真CPU
当前负载为百分之百,并且是自己部署上去的Java
应用程序,于是开始进行错误信息定位
错误定位
- 使用
jps or lsof -i:{port}
得到目前Java程序的PID - 使用命令
ps -mp <PID> -o THREAD,tid,time
进行打印所有的线程信息状态 - 筛选出
CPU
占用率较高的线程tid
- 使用命令
printf "%x\n" tid
得到线程的16进制表示 - 使用
jstack <PID> > xxx.txt
将当前Java
程序的线程栈打印出来,然后根据上面得到的线程的16进制表示,定位到具体的线程进行具体分析
代码定位
发现是HBase_MQ_THREAD-*
的线程出现了高CPU
占用,于是查看代码,发现是因为Distruptor
的替换等待策略选择不当的问题
1 | private Disruptor<Message> disruptor(int ringBufferSize) { |
查看代码注释,发现YieldingWaitStrategy
策略会通过消耗CPU时钟周期来达到优化延迟的目的,会导致CPU
占用率达到100%
This strategy will use 100% CPU, but will more readily give up the CPU than a busy spin strategy if other threads require CPU resource.
附上代码
1 | public final class YieldingWaitStrategy implements WaitStrategy { |
因此进行了策略的替换,将YieldingWaitStrategy
改为了默认的策略BlockingWaitStrategy