性能优化实战:告警一直报cpu io wait过高
在告警平台,近期经常收到存储管理节点的告警信息,如下:
"message": "节点 node1 CPU IO Wait 当前是 243.2330043859647%",
"suggestion_i18n": {
"en": "检查CPU负载",
"zh": "检查CPU负载"
},
我们先从基本信息来判断:
这是告警平台根据告警指标机制来抓取的数据,汇总计算后得出的,显然这个值太高了(正常单个值不会超过100%)。 这里CPU IO
Wait异常高,大体可以判断是系统IO等待时间长,可能是磁盘,也可能是网络,CPU基本不处于紧张状态。
既然出现了IO瓶颈,接下来重点分析对象应该放到IO子系统上。
登录出现问题的节点,先查一下基本信息
root@node:~# free -wh
total used free shared buffers cache available
Mem: 125G 28G 14G 34G 352M 82G 79G
Swap: 29G 29G 0B
root@node:~# df -h
Filesystem Size Used Avail Use% Mounted on
udev 63G 63G 0 100% /dev
tmpfs 13G 1.3G 12G 11% /run
/dev/sda1 46G 19G 26G 42% /
tmpfs 63G 0 63G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 63G 0 63G 0% /sys/fs/cgroup
/dev/sda3 805G 170G 594G 23% /test
tmpfs 13G 0 13G 0% /run/user/1000
root@node:~# uptime
20:18:42 up 1620 days, 3:34, 2 users, load average: 0.66, 0.84, 1.32
根据这些信息我们可以看到系统的负载并不高,磁盘空间也充足,内存的free空间也还有一些14G。
但是swap被占满了,根据之前的文章我们知道,还有空余内存的情况下,swap不可能被占满,这是互相矛盾的。这种现象说明,在系统压力大的时候大量内存页被换出到swap,但是内存压力释放之后,这些内存页并没有及时从swap中收回,可能存在进程问题。
但目前我们的告警主要集中在IO方面,并不能直接跟“swap的占满”这一问题完全挂钩,因为目前有空闲内存,但仍然在告警。
我们继续沿着io这条路径使用iostat/top/vmstat等工具排查一下系统IO和CPU的使用情况。
# 使用iotop找到高I/O进程
iostat -x 2
Linux 4.15.0-58-generic (zw1bnr02n00) 11/10/2025 _x86_64_ (64 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
1.31 0.00 0.10 0.04 0.00 98.54
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 9.80 0.49 35.70 29.74 994.55 56.60 0.01 0.29 2.62 0.26 0.07 0.27
avg-cpu: %user %nice %system %iowait %steal %idle
1.07 0.00 0.07 0.00 0.00 98.86
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 3.00 0.00 21.50 0.00 98.00 9.12 0.00 0.00 0.00 0.00 0.00 0.00
在连续执行一段时间后,发现%util的值并不高说明磁盘并没有饱和。同时await也没有远大于svctm,说明IO请求也没有出现大量积压。这里await指的是IO请求平均等待时间;svctm指的是磁盘服务时间。
我们继续用 iotop -o 命令看一下IO等待进程,可以查看进程的 IO 实时消耗。

使用 pidstat -d 1 命令实时查看进程的 IO 读写速率(kB_read/s、kB_wrtn/s),找一下是否 IO 占用高的进程。
root@node:~# pidstat -d 1
Linux 4.15.0-58-generic (zw1bnr02n00) 11/10/2025 _x86_64_ (64 CPU)
09:26:29 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
09:26:30 PM 0 854 0.00 19.23 0.00 0 jbd2/sda1-8
09:26:30 PM 110 5399 0.00 7.69 0.00 0 mysqld
09:26:30 PM 0 21441 0.00 19.23 0.00 0 prometheus
09:26:30 PM 0 40237 0.00 76.92 0.00 0 java
09:26:30 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
09:26:31 PM 0 1617 0.00 4.00 0.00 0 jbd2/sda3-8
09:26:31 PM 110 5399 0.00 4.00 0.00 0 mysqld
09:26:31 PM 0 21441 0.00 4.00 0.00 0 prometheus
09:26:31 PM 0 40237 0.00 116.00 0.00 0 java
我们还可以使用 mpstat -P ALL 1 5 命令查询一下系统是否调用频繁、或者内核处理任务是否繁重。
root@node:~# mpstat -P ALL 1 1
Linux 4.15.0-58-generic (zw1bnr02n00) 11/10/2025 _x86_64_ (64 CPU)
09:36:15 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
09:36:16 PM all 0.05 0.00 0.02 0.02 0.00 0.00 0.00 0.00 0.00 99.92
09:36:16 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
09:36:16 PM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
09:36:16 PM 2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
......
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 0.05 0.00 0.02 0.02 0.00 0.00 0.00 0.00 0.00 99.92
Average: 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
Average: 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
Average: 2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
......
到这里,很多迹象表明,基本上IO这一块并没有太大的问题。那是不是硬盘可能存在问题,只在特定的时间发生呢。我们继续查一下内核中是否有io错误,或者磁盘是否有故障。
dmesg -T| grep -I error # 检查内核消息中是否有I/O错误
smartctl --all /dev/sda # 输出磁盘信息
经过查看,也并没有出现任何问题。
鉴于文章篇幅不过长,先写到这里。后面经过排查,后来之所以报这个错误,是因为Prometheus告警规则有问题,优化后正常了。
至于上面提到swap被占满的问题,后面我们再单独探讨如何使用工具来排查,以及在生产环境下如何更安全的释放掉占满的swap。
直接释放swap缓存并不是一个推荐的操作,因为swap中存放的是被换出的内存页,这些页通常是在物理内存不足时被交换到swap磁盘上的。释放swap缓存实际上意味着将swap空间中的内容清除,但这并不安全,因为如果这些数据再次被需要,它们必须从磁盘重新读取,而且如果物理内存不足,可能还会再次触发交换。
虽然上面的过程比较简单,但是也提供了一些出现类似问题时的排查思路。
1725

被折叠的 条评论
为什么被折叠?



