我所理解的其他问题·第8篇·线上CPU警报如何排查根因?

186 阅读5分钟

上周某天晚上上线,完事后当所有人准备高高兴兴下班的时候,群里报警机器人突然不合时宜地冒泡了:服务器CPU资源突然升高了,照理说这个点应该不会有很多用户使用我们系统,估计是某个定时任务或者开放API导致的。

CPU警报

没办法,又得打开已经关闭了的显示器,开始排查到底是哪里的问题。

1. 排查过程记录

1.1 top

第一步是用top命令查看CPU资源分配情况及进程号。

进程占用CPU情况

从图中可以看到,PID=31439的进程的%CPU值为100%,说明这条进程占用CPU的时间已经到达100%,线上的警报就是由这个进程发出的。

如果不确定,可以用jps -l命令查看线上服务器正在运行的Java项目,对比进程id来确定警报来源。

1.2 top -Hp 进程PID

第二步是用top -Hp 进程PID命令查看该进程下各线程CPU资源的使用情况。

线程占用CPU情况

这条命令是为了确定是哪个线程执行的任务导致CPU警报的,从图上可以看到线程PID=31440,它占用了99%的CPU。

1.3 printf "0x%x\n" 线程PID

第三步是用printf "0x%x\n" 线程PID将线程PID转化为十六进制。

线程PID十六进制

这一步也可以用其他方式代替,比如“在线十进制转十六进制”网站,获取线程PID的十六进制是因为在线程堆栈文件中,线程号就是用十六进制来表示的。

1.4 jstack 进程PID | vim +/十六进制线程PID -

第四步是用jstack 进程PID | vim +/十六进制线程PID -命令输出进程堆栈信息,同时通过十六进制线程号定位到指定线程号堆栈信息。

线程堆栈文件

从上图可以看到,这个线程执行的代码是在Demo.java:4

最后就是打开工程,查看这个类的源码,看看为什么在这里会消耗大量CPU。

Demo.java文件是本文的实例代码,它是一个美丽的死循环。

也可以分两步完成以上操作:

  • jstack 进程PID > demo.txt导出进程堆栈信息,导出到demo.txt文件
  • 打开堆栈文件搜索十六进制线程ID号

2. top 执行结果

操作系统版本为:CentOS Linux release 7.3.1611 (Core),可通过cat /etc/redhat-release命令查看。

然后这里记录一下 top 命令的各个参数的意义,平常只是用来看cpu和内存,其他指标还真啥都不知道,以后“查字典”也方便。

第一行:概况,与uptime命令的执行结果相同。

  • HH:mm:ss:系统当前时间
  • up x days, HH:mm:从本次开机到当前时间的系统运行时间(单位:分钟)
  • x user:当前登录到本机的用户数
  • load average: x.xx, x.xx, x.xx:系统在1分钟、5分钟、15分钟内的系统平均负载值
    • 关于负载均衡值和算法的介绍可以看这篇文章
    • 当然我也没看完上面那篇文章(全英文有点看不过来),但是文章中有一段解释对了解系统平均负载值是有帮助的:
      • 如果平均值为0.0,那么系统是闲置的
      • 如果1分钟平均值大于5分钟或15分钟的负载值,那么负载在增加
      • 如果1分钟平均值低于5分钟或15分钟的负载值,那么负载在减少
      • 如果这三个值高于CPU数,那么你可能有性能问题(视情况而定)

第二行:进程信息

  • x total:所有进程数
  • x running:正在运行的进程数
  • x sleeping:休眠进程数
  • x zombie:僵尸进程数
    • 僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。

第三行:CPU状态

  • x.x us:用户空间(user space)消耗CPU时间百分比
  • x.x sy:内核空间(kernel space,system)消耗CPU时间百分比
  • x.x ni:调整过用户态优先级的进程(niced user processes)消耗CPU时间百分比
  • x.x wa:空闲(wait space)CPU时间百分比
  • x.x hi:处理硬中断(hardware interrupt)的CPU时间百分比
  • x.x si:处理软中断(software interrupt)的CPU时间百分比
  • x.x st:等待CPU资源(steal time)的时间百分比

第四行:内存状态

  • xxx total:内存总量
  • xxx free:空闲内存量
  • xxx used:已使用内存量
  • xxx buff/cache:缓存和page cache占用的内存量

第五行:交换区状态

  • xxx total:内存总量
  • xxx free:空闲内存量
  • xxx used:已使用内存量
  • xxx avail Mem:可用于进程下一次分配的物理内存数量

第七行至末尾:进程详细信息

  • PID:进程PID
  • USER:进程所有者的用户名
  • PR:进程调度优先级
  • NI:从用户空间视角的进程优先级(niced值),值越低优先级越高
  • VIRT:进程使用的虚拟内存(kb),VIRT=SWAP+RES
  • RES:进程使用的(未被换出的)物理内存(kb),RES=CODE+DATA
  • SHR:共享内存大小(kb)
  • S:进程状态
    • D:不可中断的睡眠状态
    • R:运行
    • S:睡眠
    • T:跟踪/停止
    • Z:僵尸进程
  • %CPU:进程占用CPU时间比例
  • %MEM:进程占用的物理内存比例
  • TIME+: 进程占用的CPU时间总量(ms)
  • COMMAND:运行进程使用的命令

3. 参考资料

版权声明:本文为Planeswalker23所创,转载请带上原文链接,感谢。