今早收到大量机器负载高的告警,登录服务器查看后发现 load 值高,但 CPU 使用率正常。
问题分析
平均负载是指单位时间内,系统处于运行队列的平均长度,运行队列的进程包括可运行状态和不可中断状态进程,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
-
可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
-
不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程。
当 CPU 使用率很低,但 load 很高时, 我们可以推断大量线程处于 I/O 操作状态,系统的性能瓶颈出现在磁盘或者网络 I/O。
找出处于运行队列的进程
$ ps -eTo stat,pid,tid,ppid,comm --no-header | sed -e 's/^ \*//' | perl -nE 'chomp;say if (m!^\S*[RD]+\s*!)'
D+ 6351 6351 6350 python
D 18742 18742 18741 updatedb.mlocat
$ ps -ef |grep 6351
sre 6351 6350 0 04:31 pts/2 00:00:00 /usr/bin/python /home/ubuntu/.ansible/tmp/ansible-tmp-1607200299.1-63852466099206/AnsiballZ_setup.py
root 25973 25898 0 09:31 pts/3 00:00:00 grep --color=auto 6351
使用 strace
跟踪
strace /usr/bin/python /home/sre/.ansible/tmp/ansible-tmp-1607219505.47-170658201224102/AnsiballZ_setup.py && sleep 0
fstat(7, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
munmap(0x7f5b09f23000, 4096) = 0
select(8, [5 7], [], [5 7], {1, 0}) = 1 (in [5], left {0, 999432})
read(5, "DEVLINKS=/dev/disk/by-id/nvme-Am"..., 9000) = 855
select(8, [5 7], [], [5 7], {1, 0}) = 2 (in [5 7], left {0, 999998})
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2809, si_status=0, si_utime=11, si_stime=11} ---
read(5, "", 9000) = 0
read(7, "", 9000) = 0
wait4(2809, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2809
close(5) = 0
close(7) = 0
chdir("/root") = 0
statfs("/Core",
卡在了 statfs("/Core"
处,/Core 为 NFS 挂载点, 而此时 NFS 挂载超时,执行 ls /Core
同样卡住不动。将对应的 ansible python 进程 kill 后,load 值就降下来了。