• 记录一次线上服务CPU飙高问题


    2023.07.20 20:01:38线上一个服务发生了CPU过高的告警,

    看告警信息当前的CPU使用率已经达到了82.65%,问题已经很严重,赶紧开始排查起来。来复盘下如何排查这类问题,

    一、排查方法

    1、找到cpu过高的进程ID

    收到告警后,第一件事要做的就是找到CPU过高的程序的线程id(pid),可以使用jps或ps -ef |grep java两个命令均可,

    1.1、jps

    使用jps命令

    jps

    得到下面的结果

    也就是进程ID是6。

    再看使用ps的结果

    1.2、ps

    使用ps命令

    ps -ef |grep java

    得到下面的结果

    可以看到进程ID也是6。

    当然除了上面两个命令,还可以使用top,也可以很快找到CPU过高的服务进程ID。

    我们已经知道了cpu过高的服务进程ID是6,但仅知道进程ID是无用的,需要进一步知道这个进程中哪些线程占用CPU过高。

    2、找到cpu过高的线程ID

    这里使用的是top命令

    top -Hp 6

    得到的结果如下

    可以看到线程1110 1125 1112 1121等占用CPU过高,基本都在80%,基本可以断定就是这些线程在占用CPU。

    找到占用CPU过高的线程后,就要看下相应的堆栈信息。

    1.3、打印进程堆栈

    使用jstack命令,jstack命令可以打印出进程的堆栈,通过堆栈信息可以分析到线程的执行情况,

    jstack -l 6

    可以看到很多类似这样的信息,这些信息中有一个很重要的那就是nid=0x11,这个是代表的线程ID,聪明的你也一定知道这里是16进制,和刚才使用top -Hp命令看到的不一样,那里是10进制的。

    为了找到线程占用cpu过高的堆栈,需要把线程ID做一次进制转换,既由10进制转换为16进制,

    例,1110--》0x456    1125--》0x465

    以0x465为例,在堆栈中查找相应的线程堆栈,

    1.4、查找线程堆栈

    使用0x465查找其对应的线程堆栈

    可以看到线程0x465的线程状态是RUNNABLE,而且看到了很多正则的调用,继续往下看,找到了调用的代码,

    最后分析是由于死循环引起的线程占用CPU过高。

    上面是我把文件下载下来进行的查找,那如何生成堆栈文件,可以使用下面的命令

    jstack -l 6 > dump.txt

    生成后下载到本地即可。

    如果线上环境无法下载,则只能通过命令进行查找

    jstack -l 6 | grep -A 10 0x465

    这样便可以看到相应的内容了。

    二、fastthread

    有没有觉得使用jstack命令导出文件后自己分析很麻烦,没事有工具,可以使用fastthread。

    其网址是:https://fastthread.io/

    将jstack或者其他工具dump的堆栈文件上传到该网站同样可以分析出结果。

    将刚才的文件上传后,得到分析报告,由于是分析CPU过高,重点看cpu threads即可。

    可以看到nativeId:1125即对应top -Hp出的线程ID,这里fastThread已经进行了进制转换,无需手动操作了,很贴心。点击查看完整的堆栈信息即可分析出相应的问题。

    三、总结

    一般程序CPU过高,大多数和死循环有关,分析此类问题的一般步骤是,

    1、使用jps/ps -ef |grep java/top等命令找到进程ID,即pid;

    2、使用top -Hp pid 找到进程中占用CUP的线程ID;

    3、使用jstack打印堆栈;

    4、使用线程ID在堆栈中找到对应的线程堆栈;

    5、分析线程堆栈,找到问题;

     

    参考:

    (7条消息) jstack命令解析_fightingD&W的博客-CSDN博客

    Linux命令之Grep——文本搜索 - 阅读清单 - 腾讯云开发者社区-腾讯云 (tencent.com)

     

    推荐阅读

    因为一条DDL,差点搞挂整个系统,这次真的长了教训

    一次性掌握innodb引擎如何解决幻读和不可重复读

    花了半天时间,使用spring-boot实现动态数据源,切换自如

     

  • 相关阅读:
    每日一题·729.我的日程安排表
    算法~PBKDF2-SHA让密码更安全
    SpringBean的生命周期
    枚举(enum)/共用体(union)/结构体(struct)---详解
    Python创建“全是1”的数组,np.ones()函数
    一致性检验-简单Kappa
    笙默考试管理系统-MyExamTest----codemirror(22)
    Arm64体系架构-MPIDR_EL1寄存器
    【无标题】
    构建可维护的大规模应用:框架架构的最佳实践
  • 原文地址:https://www.cnblogs.com/teach/p/17582912.html