记一次CPU突然飙升到 100% 问题排查

「爱情、让人受尽委屈。」 2021-09-18 04:38 632阅读 0赞

线上 CPU 飚高问题该如何定位问题呢?

是因为线程太多,导致上下文切换?
还是因为应用代码中出现了死循环?
还是GC频繁导致 CPU 突然飙升?
该如何入手呢?

首先要知道那些情况会导致 CPU 的突然飙升:

  1. 频繁GC,访问量高时,有可能造成频繁的GC、甚至FGC。当调用量大时,内存分配过快,就会造成GC线程不停的执行,导致CPU飙高
  2. 序列化与反序列化,例如应用代码执行xml解析时,调用量增大的情况下,可能导致了CPU被打满
  3. 加密、解密
  4. 正则表达式校验(正则匹配回溯问题)
  5. 线程上下文切换、当启动了很多线程,而这些线程都处于不断的阻塞状态(锁等待、IO等待等)和执行状态的变化过程中。当锁竞争激烈时,很容易出现这种情况
  6. 某些线程在做无阻塞的运算,简单的例子while(true)中不停的做运算,没有任何阻塞。写程序时,如果需要做很久的计算,可以适当将程序sleep下

实际案例
在一次生产切库时,暂停了 kafka 的消费,大概切了8个小时,导致 kafka 内堆积了大量的数据(ps:一些统计数据),当重新启动消费的时候,CPU 迅速打满。
排查问题:
因为在消费kafka时,使用了多线程进行消费,并且使用了 Executor 框架提供的 Executors.newFixedThreadPool(50),设置了 50,导致产生大量的线程在做上下文切换
vmstat 可以查看线程上下文切换的频率

  1. vmstat 1 10

在这里插入图片描述
参考文章:Linux vmstat命令详解

将线程数降为6,CPU 恢复正常。

这是在明确知道可能出现CPU飙升出现的情况。
大多数情况下是不会明确知道问题出在哪里的?那该如何进行排查呢?

  1. 使用 top 命令查找 cpu 占比最高的线程

    top

在这里插入图片描述

  1. 根据前面的 pid,使用 top -H -p pid 查看该进程的线程信息,查看是那个线程耗费 CPU

    top -H -p pid

  2. 找到占用 cpu 最高的线程的 pid,例如 88

  3. 使用 printf “%x\n” 88,打印该线程的 16 进制数值

    print “%x\n” 88
    58

  4. 使用 jstack 命令将进程 pid 的堆栈信息倒出来

    jstack pid > pid.log

  5. 打开 pid.log, 查找 线程 nid 为 58 的线程即为 cpu 最高占用的线程。

tips
现在大部分应用都是使用docker运行,在查找的过程中,如何对应docker内的进程pid与宿主机的进程pid
使用 docker top name

在这里插入图片描述
如上 pid 即为该 docker 镜像在宿主机中的pid

一个可以在线分析堆栈信息的网站:https://fastthread.io/
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,632人围观)

还没有评论,来说两句吧...

相关阅读

    相关 cpu飙升问题排查

    前言 首先问题是这样的,周五正在写文档,突然收到了线上报警,发现cpu占用达到了90多,上平台监控系统查看容器,在jvm监控中发现有一个pod在两个小时内产生了61次yo

    相关 CPU飙升排查思路

    最近公司有个需求是对接E签宝的,也就是CA认证,大致的情况就是我们拿着文件去E签宝做CA认定,简单的理解就是拿着合同去E签宝盖章。 因为是对接三方的吗,所以在调E签宝服务的