I/O问题一直是一个比较难定位的问题,今天线上环境遇到了I/O 引起的CPU负载问题,看到了如下这篇比较好的文章,完饭后的我还在和西红柿和黄瓜在减肥的路上抗争,正好将原文翻译成中文,供广大同胞品鉴
Linux 有许多可用来查找问题的简单工具,也有许多是更高级的
I/O Wait 就是一个需要使用高级的工具来debug的问题,当然也有许多基本工具的高级用法。I/O wait的问题难以定位的原因是因为我们有很多工具可以告诉你说I/O 受限了,但是并没有告诉你具体是那个进程引起的(哪些进程们)
确认是否是I/O问题导致系统缓慢
确认是否是I/O导致的系统缓慢我们可以使用多个命令,但是,最简单的是unix的命令 top
1 2 3 4 5 6 7 |
# top top - 14:31:20 up 35 min, 4 users, load average: 2.25, 1.74, 1.68 Tasks: 71 total, 1 running, 70 sleeping, 0 stopped, 0 zombie Cpu(s): 2.3%us, 1.7%sy, 0.0%ni, 0.0%id, 96.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 245440k total, 241004k used, 4436k free, 496k buffers Swap: 409596k total, 5436k used, 404160k free, 182812k cached |
从Cpu一行我们可以看到浪费在I/O Wait上的CPU百分比;这个数字越高说明越多的CPU资源在等待I/O权限
1 2 3 |
wa -- iowait Amount of time the CPU has been waiting for I/O to complete. |
查找那块磁盘正在被写入
上边的top命令从一个整体上说明了I/O wait,但是并没有说明是哪块磁盘影响的,想知道是哪块磁盘引发的问题,我们用到了另外一个命令 iostat 命令
1 2 3 4 5 6 7 8 9 |
$ iostat -x 2 5 avg-cpu: %user %nice %system %iowait %steal %idle 3.66 0.00 47.64 48.69 0.00 0.00 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 44.50 39.27 117.28 29.32 11220.94 13126.70 332.17 65.77 462.79 9.80 2274.71 7.60 111.41 dm-0 0.00 0.00 83.25 9.95 10515.18 4295.29 317.84 57.01 648.54 16.73 5935.79 11.48 107.02 dm-1 0.00 0.00 57.07 40.84 228.27 163.35 8.00 93.84 979.61 13.94 2329.08 10.93 107.02 |
上边的例子中,iostat 会每2秒更新一次,一共打印5次信息, -x 的选项是打印出扩展信息
第一个iostat 报告会打印出系统最后一次启动后的统计信息,这也就是说,在多数情况下,第一个打印出来的信息应该被忽略,剩下的报告,都是基于上一次间隔的时间。举例子来说,这个命令会打印5次,第二次的报告是从第一次报告出来一个后的统计信息,第三次是基于第二次 ,依次类推
在上面的例子中,sda的%utilized 是111.41%,这个很好的说明了有进程正在写入到sda磁盘中。因为例子中的测试系统只有一块磁盘,当一个服务器中有多快磁盘的时候,这个命令可以很好的缩小我们需要查找的进程的范围
除了%utilized 外,我们可以得到更改丰富的资源从iostat,例如每毫秒读写请求(rrqm/s & wrqm/s)),每秒读写的((r/s & w/s),当然还有更多。在上边的例子中,我们的项目看起来正在读写非常多的信息。这个对我们查找相应的进程非常有用。
Finding the processes that are causing high I/O
查找引起高I/O wait 对应的进程
iotop
1 2 3 4 5 |
# iotop Total DISK READ: 8.00 M/s | Total DISK WRITE: 20.36 M/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 15758 be/4 root 7.99 M/s 8.01 M/s 0.00 % 61.97 % bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp |
最简单的方式来发现罪魁祸首是使用命令iotop,通过查看iotop的统计信息,我们可以很容易的指导bonnie++就是罪魁祸首
虽然iotop是一个非常强大的工具,并且使用简单,但是它并不是默认安装在所有的linux操作系统中。并且我个人倾向不要太依赖那些默认没有安装的命令。一个系统管理员可能会发现他无法立即安装额外的除默认程序之外的软件,除非等到后边的维护的时间。
如果iotop并没有安装,下面的步骤会教会你如何缩小目标进程的范围
进程的状态
ps 命令对内存和CPU有一个统计,但是他没有对磁盘I/O的统计,虽然他没有显示磁盘I/O,但是它显示进行的状态,我们可以用来知道一个进程是否正在等待I/O
The ps state field provides the processes current state; below is a list of states from the man page.
ps state状态来表示了process现在的状态,下面是各个状态的帮助文档
1 2 3 4 5 6 7 8 9 |
PROCESS STATE CODES D uninterruptible sleep (usually IO) R running or runnable (on run queue) S interruptible sleep (waiting for an event to complete) T stopped, either by a job control signal or because it is being traced. W paging (not valid since the 2.6.xx kernel) X dead (should never be seen) Z defunct ("zombie") process, terminated but not reaped by its parent. |
那些等待I/O的进程的状态一般是“uninterruptible sleep”,或者“D”,我们可以很容易的查找到正在等待I/O的进程
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# for x in `seq 1 1 10`; do ps -eo state,pid,cmd | grep "^D"; echo "----"; sleep 5; done D 248 [jbd2/dm-0-8] D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp ---- D 22 [kswapd0] D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp ---- D 22 [kswapd0] D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp ---- D 22 [kswapd0] D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp ---- D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp ---- |
上边的例子会循环的输出状态是D的进程,每5秒一次,一共10次
从输出我们可以知道 bonnie++ 的pid是16528 ,它比其他的进程更可疑,它老师在waiting,这个时候,bonnie++貌似就是我们想找到的进程,但是,单纯从它的状态,我们没有办法证明是bonnie++引起的I/O问题
为了确认我们的怀疑,我们可以使用 /proc文件系统,每个进程目录下都有一个叫io的文件,里边保存这和iotop类似的信息
1 2 3 4 5 6 7 8 9 |
# cat /proc/16528/io rchar: 48752567 wchar: 549961789 syscr: 5967 syscw: 67138 read_bytes: 49020928 write_bytes: 549961728 cancelled_write_bytes: 0 |
read_bytes和write_bytes是这个进程从磁盘读写的字节,在这个例子中,bonnie++进程读取了46M的数据并且写入了524的数据到磁盘上。这样的数据对于其他的进程可能并不是很多,但是在我们例子中,这足够引发系统的问题。
查找那个文件引起的I/Owait
lsof 命令可以展示一个进程打开的所有文件,或者打开一个文件的所有进程。从这个列表中,我们可以找到具体是什么文件被写入,根据文件的大小和/proc中io文件的具体数据
(这段翻译的有点绕,翻译好的直接留言好了http://www.503error.com)
我们可以使用-p <pid>的方式来减少输出,pid是具体的进程
1 2 3 4 5 6 7 8 9 10 |
# lsof -p 16528 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bonnie++ 16528 root cwd DIR 252,0 4096 130597 /tmp <truncated> bonnie++ 16528 root 8u REG 252,0 501219328 131869 /tmp/Bonnie.16528 bonnie++ 16528 root 9u REG 252,0 501219328 131869 /tmp/Bonnie.16528 bonnie++ 16528 root 10u REG 252,0 501219328 131869 /tmp/Bonnie.16528 bonnie++ 16528 root 11u REG 252,0 501219328 131869 /tmp/Bonnie.16528 bonnie++ 16528 root 12u REG 252,0 501219328 131869 <strong>/tmp/Bonnie.16528</strong> |
为了更深入的确认这些文件被频繁的读写,我们可以通过如下命令来查看
1 2 3 4 |
# df /tmp Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/workstation-root 7667140 2628608 4653920 37% / |
从上面的命令结果来看,我们可以确定/tmp 是我们环境的逻辑磁盘的根目录
1 2 3 4 5 6 7 8 9 10 11 12 |
# pvdisplay --- Physical volume --- PV Name /dev/sda5 VG Name workstation PV Size 7.76 GiB / not usable 2.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 1986 Free PE 8 Allocated PE 1978 PV UUID CLbABb-GcLB-l5z3-TCj3-IOK3-SQ2p-RDPW5S |
通过pvdisplay我们能看到/dev/sda5其实就是我们用来创建逻辑磁盘的具体磁盘。通过以上的信息我们可以放心的说lsof的结果就是我们要查找的文件
原文地址:http://bencane.com/2012/08/06/troubleshooting-high-io-wait-in-linux/
Latest posts by Zhiming Zhang (see all)
- aws eks node 自动化扩展工具 Karpenter - 8月 10, 2022
- ReplicationController and ReplicaSet in Kubernetes - 12月 20, 2021
- public key fingerprint - 5月 27, 2021
kvm vps 2016/05/13 07:36
兄弟,交换链接吗?
Zhiming Zhang 博主 2016/05/13 20:24
@ Pr值至少得1吧...
瑶瑶 2016/09/20 14:58
文章不错,欢迎回访http://www.3c7.net
自行车 2016/09/22 14:51
有点看不懂
广州网站建设 2018/05/08 11:15
感谢分享,学习了!