load avg
服务器负载实际上指的就是当前操作系统 Running(执行中) 及 Runnable(就绪等待执行) 的任务队列数量(实际情况可能会包含其他,参看 wiki),实际展示了当前系统执行的压力——如果就绪执行的队列过长,那么任务执行的周期就越长,可以理解为服务器已经无法承担如此大的压力,只能排队执行了。
类比于一个面包店,正常情况下,一个服务员可以解决店内某一时刻一人结账,如果此时有两人结账,那么其中一人只能等待。此时结账还可控,只是第二位客人结账时间会延长,但如果有十人同时结账,此时只能一个接一个的排队结账了,最后一位客人的结账周期就会非常漫长了。
linux load avg 可以通过 uptime
\ top
等指令查看,也可以通过读取文件 /proc/loadavg
获取相关数值。
$ uptime
14:34:03 up 10:43, 4 users, load average: 0.06, 0.11, 0.09
load avg 后跟有三个数值,分别以逗号分隔开,这三个数字分别代表了系统近 1 分钟、5 分钟、15 分钟的平均负载情况。
实时的系统运行情况可以通过 vmstat
查询,获取到更细粒度的系统运行状态。
# 以每 1 秒为间隔,连输打印五次
$vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
4 1 0 2311684 178948 18389776 0 0 3 189 17 9 13 8 79 0 0
1 0 0 2311404 178952 18390256 0 0 0 384 18457 32160 3 3 94 0 0
2 1 0 2312008 178952 18390368 0 0 0 608 18300 31971 5 3 92 1 0
1 0 0 2311052 178952 18390636 0 0 0 636 18108 31634 3 3 94 1 0
3 1 0 2311168 178952 18390784 0 0 0 576 19212 32975 5 3 92 0 0
问题排查
通过 CPU 使用率定位
通过 CPU 的使用率来定位某个进程/线程的运行问题。
执行方案:
1. 先定位出 CPU 使用率较高的进程,找到对应的进程 id
$top
# 进入交互界面后,按 P 使进程按照 CPU 使用率排序
2. 找到对应进程的使用 CPU 较高的子进程
$top -Hp <pid>
# <pid> 就是第一步查出来的进程 id
此时已经能定位到某些 CPU 占用较高的进程
如果是 JVM 项目,那么可以继续向下定位到 JVM 的执行堆栈。
JVM 项目
3. 将第二步得到的进程 id 转换为十六进制
$printf "0x%x\n" <pid>
# <pid> 是第二步查出的进程 id
4. 将第三步得到的十六进制和 jstack 比较找到堆栈
$jstack <pid> > jstack.tmp
# 打印 JVM 进程堆栈到 jstack.tmp 文件
# 后续只需要在文件中搜索第三步的十六进制字符串,即可找到其对应的堆栈
以上步骤已有脚本实现,可以参考使用。 [^1] 不过在多用户的 linux 中可能会出现使用上的问题,所以基本的排查原理还是要熟知。
TODO
- sar 工具
- iostat 工具
[^1]: 查找 CPU 使用最高的 Java 线程
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 [email protected]