IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 一次线上服务CPU100%的排查过程 -> 正文阅读

[Java知识库]一次线上服务CPU100%的排查过程

前言

突然收到线上服务cpu达到100%的报警短信,于是立即展开排查。

排查过程

理论步骤

一、找到最耗CPU的进程
工具:top
方法:
执行top -c ,显示进程运行信息列表
键入P (大写p),进程按照CPU使用率排序

二:找到最耗CPU的线程
工具:top
方法:
top -Hp PID,显示一个进程的线程运行信息列表
键入P (大写p),线程按照CPU使用率排序

三:将线程PID转化为16进制
工具:printf
之所以要转化为16进制,是因为堆栈里,线程id是用16进制表示的。

四:查看堆栈,找到线程在干嘛
工具:pstack/jstack/grep
打印进程堆栈 通过线程id,过滤得到线程堆栈

实战操作

零,发现服务器上安装的不知一个Java版本,于是首先确定下,通过如下 命令。

[root@service-dev ~]# find / -name java
/etc/java
/etc/pki/java
/etc/pki/ca-trust/extracted/java
/etc/alternatives/java
/var/lib/alternatives/java
/usr/share/java
/usr/bin/java
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre/bin/java
/usr/lib/java

一,找到耗CPU进程PID
通过top -c命令,可以发现进程PID 29812消耗的CPU明显是最多

二,找出耗CPU的线程
可以利用ps命令

[root@service-dev ~/consume-service]# ps -mp 29812 -o THREAD,tid,time
USER     %CPU PRI SCNT WCHAN  USER SYSTEM   TID     TIME
root     96.3   -    - -         -      -     - 00:01:04
root      0.0  19    - futex_    -      - 29812 00:00:00
root      9.2  19    - futex_    -      - 29813 00:00:06
root      1.2  19    - futex_    -      - 29814 00:00:00
root      0.0  19    - futex_    -      - 29815 00:00:00
root      0.0  19    - futex_    -      - 29816 00:00:00
root      0.0  19    - futex_    -      - 29817 00:00:00
root     12.5  19    - futex_    -      - 29818 00:00:08
root      3.5  19    - futex_    -      - 29819 00:00:02
root      0.0  19    - futex_    -      - 29820 00:00:00
root      0.0  19    - futex_    -      - 29821 00:00:00
root      0.0  19    - futex_    -      - 29833 00:00:00
root      0.0  19    - futex_    -      - 29834 00:00:00
root      0.0  19    - futex_    -      - 29836 00:00:00
root     87.9  19    - -         -      - 29840 00:00:44
root      0.0  19    - ep_pol    -      - 29841 00:00:00
root      0.0  19    - ep_pol    -      - 29842 00:00:00
root      0.0  19    - ep_pol    -      - 29843 00:00:00

可以明显发现线程29840占用的CPU最多。

当然,也可以通过top -Hp pid命令,将这个进程的线程显示出来。输入大写的 P 可以将线程按照 CPU 使用比例排序。

三,将10进制线程ID转换为16进制,便于后续在堆栈grep

[root@service-dev ~/consume-service]# printf "%x\n" 29840
7490

四、打印堆栈并grep除目标线程

[root@service-dev ~/consume-service]# jstack 29812 | grep ‘0x7490’ -C5 --color
"disruptor-Disruptor Main--1" #14 prio=5 os_prio=0 tid=0x00007f9038952800 nid=0x7490 runnable [0x00007f9011ad4000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.Thread.yield(Native Method)
        at com.lmax.disruptor.YieldingWaitStrategy.applyWaitMethod(YieldingWaitStrategy.java:58)
        at com.lmax.disruptor.YieldingWaitStrategy.waitFor(YieldingWaitStrategy.java:40)
        at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:56)
        at com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:159)
        at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - None

明显,可以发现是服务使用的Disruptor组件在执行YieldingWaitStrategy策略的时候,导致了CPU升高,排查的方向就很聚焦了。

四、进入业务排查Disruptor组件使用配置
1, 简单分析
业务层面:因为这个这本身是一个消费服务,消费来自RocketMQ的消息,但是稍显不合理的地方是一个Disruptor消费者处理了多个Topic业务,鉴于最近短时业务比较多,长时业务变少,所以yield的频率明显升高。
Disruptor层面:目前采用的时YieldingWaitStrategy策略,该策略是一种充分利用CPU 的策略,使用自旋 + yield的方式来提高性能。当消费线程(Event Handler threads)的数量小于 CPU 核心数时推荐使用该策略。我这边业务上同时启动的消费者线程数量明显多于4核个数,不太合理。
2,着手处理
短期处理:修改WaitStrategy策略,降低对CPU的使用。

  1. BlockingWaitStrategy:(也是默认的策略):使用的是锁的机制,其对CPU的消耗最小并且在各种不同的部署环境中能提供更加一致性的表现。
  2. SleepingWaitStrategy:在多次循环尝试不成功后,选择让出CPU,等待下次调度,多次调度后仍不成功,尝试前睡眠一个纳秒级别的时间再尝试,这种策略平衡了延迟和CPU资源占用,但延迟不均匀。
  3. YieldingWaitStrategy:无所高性能策略,在多次循环尝试不成功后,选择让出CPU,等待下次调。平衡了延迟和CPU资源占用,但延迟也比较均匀。官方对 YieldingWaitStrategy 的描述里谈道:
    当消费线程(Event Handler threads)的数量小于 CPU 核心数时推荐使用该策略。

所以,暂时调整为低消耗CPU的BlockingWaitStrategy,重新部署后解决了CPU升高问题,对业务的延迟影响也较小。

长远处理
将我们现有的业务拆分,根据不同的业务需要采用不同的消费策略。

参考

https://www.imooc.com/article/259253
https://www.cnblogs.com/lishijia/p/5549980.html 100%分析
https://blog.csdn.net/jiangzhexi/article/details/77429671 100%
https://www.cnblogs.com/crossoverJie/p/10129072.html 100%分析 Disruptor
https://crossoverjie.top/2018/08/29/java-senior/OOM-Disruptor/ Disruptor的坑
https://www.cnblogs.com/lyhero11/p/5127054.html
https://fastthread.io/

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:11:36  更:2022-06-06 17:15:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:34:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码