linux wa%过高,iostat查看io状况

Posted maxiongying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux wa%过高,iostat查看io状况相关的知识,希望对你有一定的参考价值。

命令总结:

1. top/vmstat 发现 wa%过高,vmstat b >1;

 

 

参考文章

1. 关于Linux系统指令 top 之 %wa 占用高,用`iostat`探个究竟

最近测试一项目,性能非常不理想。老版本逻辑和功能都简单时,性能是相当的好!接口点击率是万级的。谁知修改后上不了百。

    架设Jboss服务器,业务逻辑用Java处理,核心模块使用C++处理,使用JNI衔接。

    本应用对CPU和硬盘第三非常敏感,因为有压缩解压和大量数据交互。起初作压力测试时,发现服务器各资源使用都有剩余,而点击率曲线波动却非常大,简单看似乎是应用程序有问题。技术分享

    使用top查看Cpu各核的使用情况,发现一个非常诡异的现象:

         1. 经常只有部分核是满载的,另外一部分基本空闲;

         2. 在CPU满载时,%wa 的波动比较大,有时会占到较大比例。

    所以,监控整个CPU时会发现CPU使用率不高,实际上任务总是分派到某个核上且导致对应核满载。无法有效使用CPU,其它资源自然也难以有效调度。

    废话不多说,%waCPU等待磁盘写入完成的时间。莫非是磁盘忙,怎样证明是磁盘在忙?

   首先看下%wa的解释:Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.

    起初用`lsof | less`查看文件的读写情况,发现/tmp目录下有大量文件读写。经查证,是Jboss处理上传文件会默认写入到/tmp文件夹,然后再执行了一次拷贝到程序读取的目录。修改Jboss配置直接写入到程序读写目录,性能没有本质上的改变。技术分享

    关于CPU使用波动大,我们也在程序内部加了很多计时器,发现某些模块在处理并发时会有响应时间很长的情况,这点证实了为什么点击率波动很大。

    但此模块进行单进程串行测试时,每秒完成事务数是相当可观的。一个进程每秒完成的事务数都比当前测试点击率要高很多!使用多进程来测试此模块时,发现“进程数=核数”时效果最佳。于是在Java层控制同时进入此模块的数量,毕竟Java是调用JNI来使用此模块,使用全局锁来控制并发,最终结果没有想象的那么理想,但明显可以看出:通过控制并发数,能有效提高CPU的使用率,点击率也上升了一些。技术分享

    另外一个问题就是,CPU会出现一会满载,一会空闲的情况,导致点击率曲线仍然波动大的问题。商讨后决定在C++代码中加入“释放CPU控制权”的逻辑,这样就在代码层来作了一个负载均衡。点击率波动的问题得到了好转,但点击率仍然不理想,预期瓶颈是网络而实际变成了CPU

    优化了压缩解决的处理后,性能没有明显提升。这时我才想起%wa,我还没有进一步证明是磁盘的闲忙程度。使用了一些监控工具,诸如:vmstatsardstatsysstat没有发现对磁盘作非常详细的监控。最后试了下iostat,搞定!技术分享

    iostat的编译非常简单,就一个c文件,MakeFile里作者写了一句话“Cann‘t be simpler”。直接make install就在目录下生成了iostat的可执行文件,看一下帮助,执行 `iostat -cdDx 10` 。其中有一列“%b”描述了磁盘的闲忙程序,简单直接。另外还有详细的磁盘IO读写数据,帮助里也解释得非常清楚。

   再进行一次压力测试,拿着这份数据,已经绝对性的说明问题了。此时那些大牛把代码改了一下,性能立马就上去了,千兆网络直接成为系统瓶颈。并于Java的控制问题,改用Apache直接编译程序模块调用,完成变为可控,问题瞬间解决!技术分享

附上iostat的源码:

 

转自:http://hi.baidu.com/higkoo/blog/item/d4f7f822e7871cf8d6cae25e.html

 

2.iostat来对linux硬盘IO性能进行了解

 

以前一直不太会用这个参数。现在认真研究了一下iostat,因为刚好有台重要的服务器压力高,所以放上来分析一下.下面这台就是IO有压力过大的服务器
  # iostat -x 1 10
  Linux 2.6.18-92.el5xen 02/03/2009
  avg-cpu: %user %nice %system %iowait %steal %idle
  1.10 0.00 4.82 39.54 0.07 54.46
  Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
  sda 0.00 3.50 0.40 2.50 5.60 48.00 18.48 0.00 0.97 0.97 0.28
  sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  sdd 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  sde 0.00 0.10 0.30 0.20 2.40 2.40 9.60 0.00 1.60 1.60 0.08
  sdf 17.40 0.50 102.00 0.20 12095.20 5.60 118.40 0.70 6.81 2.09 21.36
  sdg 232.40 1.90 379.70 0.50 76451.20 19.20 201.13 4.94 13.78 2.45 93.16
  rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rmerge)/s
  wrqm/s: 每秒进行 merge 的写操作数目。即 delta(wmerge)/s
  r/s: 每秒完成的读 I/O 设备次数。即 delta(rio)/s
  w/s: 每秒完成的写 I/O 设备次数。即 delta(wio)/s
  rsec/s: 每秒读扇区数。即 delta(rsect)/s
  wsec/s: 每秒写扇区数。即 delta(wsect)/s
  rkB/s: 每秒读K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。(需要计算)
  wkB/s: 每秒写K字节数。是 wsect/s 的一半。(需要计算)
  avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)。delta(rsect+wsect)/delta(rio+wio)
  avgqu-sz: 平均I/O队列长度。即 delta(aveq)/s/1000 (因为aveq的单位为毫秒)。
  await: 平均每次设备I/O操作的等待时间 (毫秒)。即 delta(ruse+wuse)/delta(rio+wio)
  svctm: 平均每次设备I/O操作的服务时间 (毫秒)。即 delta(use)/delta(rio+wio)
  %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。即 delta(use)/s/1000 (因为use的单位为毫秒)
  如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘
  可能存在瓶颈。
  idle小于70% IO压力就较大了,一般读取速度有较多的wait.
  同时可以结合vmstat 查看查看b参数(等待资源的进程数)和wa参数(IO等待所占用的CPU时间的百分比,高过30%时IO压力高)
  另外还可以参考
  svctm 一般要小于 await (因为同时等待的请求的等待时间被重复计算了),svctm 的大小一般和磁盘性能有关,CPU/内存的负荷也会对其有影响,请求过多也会间接导致 svctm 的增加。await 的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明 I/O 队列太长,应用得到的响应时间变慢,如果响应时间超过了用户可以容许的范围,这时可以考虑更换更快的磁盘,调整内核 elevator 算法,优化应用,或者升级 CPU。
  队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标,但由于 avgqu-sz 是按照单位时间的平均值,所以不能反映瞬间的 I/O 洪水。
  别人一个不错的例子.(I/O 系统 vs. 超市排队)
  举一个例子,我们在超市排队 checkout 时,怎么决定该去哪个交款台呢? 首当是看排的队人数,5个人总比20人要快吧? 除了数人头,我们也常常看看前面人购买的东西多少,如果前面有个采购了一星期食品的大妈,那么可以考虑换个队排了。还有就是收银员的速度了,如果碰上了连钱都点不清楚的新手,那就有的等了。另外,时机也很重要,可能 5 分钟前还人满为患的收款台,现在已是人去楼空,这时候交款可是很爽啊,当然,前提是那过去的 5 分钟里所做的事情比排队要有意义 (不过我还没发现什么事情比排队还无聊的)。
  I/O 系统也和超市排队有很多类似之处:
  r/s+w/s 类似于交款人的总数
  平均队列长度(avgqu-sz)类似于单位时间里平均排队人的个数
  平均服务时间(svctm)类似于收银员的收款速度
  平均等待时间(await)类似于平均每人的等待时间
  平均I/O数据(avgrq-sz)类似于平均每人所买的东西多少
  I/O 操作率 (%util)类似于收款台前有人排队的时间比例。
  我们可以根据这些数据分析出 I/O 请求的模式,以及 I/O 的速度和响应时间。
  下面是别人写的这个参数输出的分析
  # iostat -x 1
  avg-cpu: %user %nice %sys %idle
  16.24 0.00 4.31 79.44
  Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
  /dev/cciss/c0d0
  0.00 44.90 1.02 27.55 8.16 579.59 4.08 289.80 20.57 22.35 78.21 5.00 14.29
  /dev/cciss/c0d0p1
  0.00 44.90 1.02 27.55 8.16 579.59 4.08 289.80 20.57 22.35 78.21 5.00 14.29
  /dev/cciss/c0d0p2
  0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  上面的 iostat 输出表明秒有 28.57 次设备 I/O 操作: 总IO(io)/s = r/s(读) +w/s(写) = 1.02+27.55 = 28.57 (次/秒) 其中写操作占了主体 (w:r = 27:1)。
  平均每次设备 I/O 操作只需要 5ms 就可以完成,但每个 I/O 请求却需要等上 78ms,为什么? 因为发出的 I/O 请求太多 (每秒钟约 29 个),假设这些请求是同时发出的,那么平均等待时间可以这样计算:
  平均等待时间 = 单个 I/O 服务时间 * ( 1 + 2 + … + 请求总数-1) / 请求总数
  应用到上面的例子: 平均等待时间 = 5ms * (1+2+…+28)/29 = 70ms,和 iostat 给出的78ms 的平均等待时间很接近。这反过来表明 I/O 是同时发起的。
  每秒发出的 I/O 请求很多 (约 29 个),平均队列却不长 (只有 2 个 左右),这表明这 29 个请求的到来并不均匀,大部分时间 I/O 是空闲的。
  一秒中有 14.29% 的时间 I/O 队列中是有请求的,也就是说,85.71% 的时间里 I/O 系统无事可做,所有 29 个 I/O 请求都在142毫秒之内处理掉了。
  delta(ruse+wuse)/delta(io) = await = 78.21 => delta(ruse+wuse)/s =78.21 * delta(io)/s = 78.21*28.57 = 2232.8,表明每秒内的I/O请求总共需要等待2232.8ms。所以平均队列长度应为 2232.8ms/1000ms = 2.23,而 iostat 给出的平均队列长度 (avgqu-sz) 却为 22.35,为什么?! 因为 iostat 中有 bug,avgqu-sz 值应为 2.23,而不是 22.35。

 

 

3. linux lsof详解

 

lsof简介
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。
lsof使用
 
lsof输出信息含义
在终端下输入lsof即可显示系统打开的文件,因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能。
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME init 1 root cwd DIR 3,3 1024 2 / init 1 root rtd DIR 3,3 1024 2 / init 1 root txt REG 3,3 38432 1763452 /sbin/init init 1 root mem REG 3,3 106114 1091620 /lib/libdl-2.6.so init 1 root mem REG 3,3 7560696 1091614 /lib/libc-2.6.so init 1 root mem REG 3,3 79460 1091669 /lib/libselinux.so.1 init 1 root mem REG 3,3 223280 1091668 /lib/libsepol.so.1 init 1 root mem REG 3,3 564136 1091607 /lib/ld-2.6.so init 1 root 10u FIFO 0,15 1309 /dev/initctl
每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件。lsof输出各列信息的意义如下:
COMMAND:进程的名称 PID:进程标识符 USER:进程所有者 FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE:文件类型,如DIR、REG等 DEVICE:指定磁盘的名称 SIZE:文件的大小 NODE:索引节点(文件在磁盘上的标识) NAME:打开文件的确切名称
其中FD 列中的文件描述符cwd 值表示应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改。
txt 类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序。其次数值表示应用
程序的文件描述符,这是打开该文件时返回的一个整数。如上的最后一行文件/dev/initctl,其文件描述符为 10。u 表示该
文件被打开并处于读取/写入模式,而不是只读 ? 或只写 (w) 模式。同时还有大写 的W 表示该应用程序具有对整个文件的写
锁。该文件描述符用于确保每次只能打开一个应用程序实例。初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,
分别表示标准输入、输出和错误流。所以大多数应用程序所打开的文件的 FD 都是从 3 开始。
与 FD 列相比,Type 列则比较直观。文件和目录分别称为 REG 和 DIR。而CHR 和 BLK,分别表示字符和块设备;
或者 UNIX、FIFO 和 IPv4,分别表示 UNIX 域套接字、先进先出 (FIFO) 队列和网际协议 (IP) 套接字。
lsof常用参数
lsof 常见的用法是查找应用程序打开的文件的名称和数目。可用于查找出某个特定应用程序将日志数据记录到何处,或者正在跟踪某个问题。
例如,linux限制了进程能够打开文件的数目。通常这个数值很大,所以不会产生问题,并且在需要时,应用程序可以请求更大的值(直到某
个上限)。如果你怀疑应用程序耗尽了文件描述符,那么可以使用 lsof 统计打开的文件数目,以进行验证。lsof语法格式是:
lsof [options] filename
常用的参数列表:
lsof filename 显示打开指定文件的所有进程 lsof -a 表示两个参数都必须满足时才显示结果 lsof -c string 显示COMMAND列中包含指定字符的进程所有打开的文件 lsof -u username 显示所属user进程打开的文件 lsof -g gid 显示归属gid的进程情况 lsof +d /DIR/ 显示目录下被进程打开的文件 lsof +D /DIR/ 同上,但是会搜索目录下的所有目录,时间相对较长 lsof -d FD 显示指定文件描述符的进程 lsof -n 不将IP转换为hostname,缺省是不加上-n参数 lsof -i 用以显示符合条件的进程情况 lsof -i[46] [protocol][@hostname|hostaddr][:service|port] 46 --> IPv4 or IPv6 protocol --> TCP or UDP hostname --> Internet host name hostaddr --> IPv4地址 service --> /etc/service中的 service name (可以不只一个) port --> 端口号 (可以不只一个)
例如: 查看22端口现在运行的情况
# lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME sshd 1409 root 3u IPv6 5678 TCP *:ssh (LISTEN)
查看所属root用户进程所打开的文件类型为txt的文件:
# lsof -a -u root -d txt COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME init 1 root txt REG 3,3 38432 1763452 /sbin/init mingetty 1632 root txt REG 3,3 14366 1763337 /sbin/mingetty mingetty 1633 root txt REG 3,3 14366 1763337 /sbin/mingetty mingetty 1634 root txt REG 3,3 14366 1763337 /sbin/mingetty mingetty 1635 root txt REG 3,3 14366 1763337 /sbin/mingetty mingetty 1636 root txt REG 3,3 14366 1763337 /sbin/mingetty mingetty 1637 root txt REG 3,3 14366 1763337 /sbin/mingetty kdm 1638 root txt REG 3,3 132548 1428194 /usr/bin/kdm X 1670 root txt REG 3,3 1716396 1428336 /usr/bin/Xorg kdm 1671 root txt REG 3,3 132548 1428194 /usr/bin/kdm startkde 2427 root txt REG 3,3 645408 1544195 /bin/bash ... ...
lsof使用实例
 
一、查找谁在使用文件系统
在卸载文件系统时,如果该文件系统中有任何打开的文件,操作通常将会失败。那么通过lsof可以找出那些进程在使用当前要卸载的文件系统,如下:
# lsof /GTES11/ COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 4208 root cwd DIR 3,1 4096 2 /GTES11/ vim 4230 root cwd DIR 3,1 4096 2 /GTES11/
在这个示例中,用户root正在其/GTES11目录中进行一些操作。一个 bash是实例正在运行,并且它当前的目录为/GTES11,另一个则显示的是vim正在编辑/GTES11下的文件。要成功地卸载/GTES11,应该在通知用户以确保情况正常之后,中止这些进程。 这个示例说明了应用程序的当前工作目录非常重要,因为它仍保持着文件资源,并且可以防止文件系统被卸载。这就是为什么大部分守护进程(后台进程)将它们的目录更改为根目录、或服务特定的目录(如 sendmail 示例中的 /var/spool/mqueue)的原因,以避免该守护进程阻止卸载不相关的文件系统。
二、恢复删除的文件
当Linux计算机受到入侵时,常见的情况是日志文件被删除,以掩盖攻击者的踪迹。管理错误也可能导致意外删除重要的文件,比如在清理旧日志时,意外地删除了数据库的活动事务日志。有时可以通过lsof来恢复这些文件。
当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录索引节点。
在/proc 目录下,其中包含了反映内核和进程树的各种文件。/proc目录挂载的是在内存中所映射的一块区域,所以这些文件和目录并不存在于磁盘中,因此当我们对这些文件进行读取和写入时,实际上是在从内存中获取相关信息。大多数与 lsof 相关的信息都存储于以进程的 PID 命名的目录中,即 /proc/1234 中包含的是 PID 为 1234 的进程的信息。每个进程目录中存在着各种文件,它们可以使得应用程序简单地了解进程的内存空间、文件描述符列表、指向磁盘上的文件的符号链接和其他系统信息。lsof 程序使用该信息和其他关于内核内部状态的信息来产生其输出。所以lsof 可以显示进程的文件描述符和相关的文件名等信息。也就是我们通过访问进程的文件描述符可以找到该文件的相关信息。
 
当系统中的某个文件被意外地删除了,只要这个时候系统中还有进程正在访问该文件,那么我们就可以通过lsof从/proc目录下恢复该文件的内容。 假如由于误操作将/var/log/messages文件删除掉了,那么这时要将/var/log/messages文件恢复的方法如下:
首先使用lsof来查看当前是否有进程打开/var/logmessages文件,如下:
# lsof |grep /var/log/messages syslogd 1283 root 2w REG 3,3 5381017 1773647 /var/log/messages (deleted)
从上面的信息可以看到 PID 1283(syslogd)打开文件的文件描述符为 2。同时还可以看到/var/log/messages已经标记被删除了。因此我们可以在 /proc/1283/fd/2 (fd下的每个以数字命名的文件表示进程对应的文件描述符)中查看相应的信息,如下:
# head -n 10 /proc/1283/fd/2 Aug 4 13:50:15 holmes86 syslogd 1.4.1: restart. Aug 4 13:50:15 holmes86 kernel: klogd 1.4.1, log source = /proc/kmsg started. Aug 4 13:50:15 holmes86 kernel: Linux version 2.6.22.1-8 ([email protected]) (gcc version 4.2.0) #1 SMP Wed Jul 18 11:18:32 EDT 2007 Aug 4 13:50:15 holmes86 kernel: BIOS-provided physical RAM map: Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000000000 - 000000000009f000 (usable) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000000009f000 - 00000000000a0000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000100000 - 000000001f7d3800 (usable) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000001f7d3800 - 0000000020000000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000e0000000 - 00000000f0007000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000f0008000 - 00000000f000c000 (reserved)
从上面的信息可以看出,查看 /proc/8663/fd/15 就可以得到所要恢复的数据。如果可以通过文件描述符查看相应的数据,那么就可以使用 I/O 重定向将其复制到文件中,如:
cat /proc/1283/fd/2 > /var/log/messages
对于许多应用程序,尤其是日志文件和数据库,这种恢复删除文件的方法非常有用。

 

 

4. Linux iostat监测IO状态[转]

Linux系统出现了性能问题,一般我们可以通过top、iostat、free、vmstat等命令 来查看初步定位问题。其中iostat可以给我们提供丰富的IO状态数据。

1. 基本使用

$iostat -d -k 1 10

参数 -d 表示,显示设备(磁盘)使用状态;-k某些使用block为单位的列强制使用Kilobytes为单位;1 10表示,数据显示每隔1秒刷新一次,共显示10次。

$iostat -d -k 1 10
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 39.29 21.14 1.44 441339807 29990031
sda1 0.00 0.00 0.00 1623 523
sda2 1.32 1.43 4.54 29834273 94827104
sda3 6.30 0.85 24.95 17816289 520725244
sda5 0.85 0.46 3.40 9543503 70970116
sda6 0.00 0.00 0.00 550 236
sda7 0.00 0.00 0.00 406 0
sda8 0.00 0.00 0.00 406 0
sda9 0.00 0.00 0.00 406 0
sda10 60.68 18.35 71.43 383002263 1490928140

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 327.55 5159.18 102.04 5056 100
sda1 0.00 0.00 0.00 0 0

tps:该设备每秒的传输次数(Indicate the number of transfers per second that were issued to the device.)。“一次传输”意思是“一次I/O请求”。多个逻辑请求可能会被合并为“一次I/O请求”。“一次传输”请求的大小是未知的。

kB_read/s:每秒从设备(drive expressed)读取的数据量;kB_wrtn/s:每秒向设备(drive expressed)写入的数据量;kB_read:读取的总数据量;kB_wrtn:写入 的总数量数据量;这些单位都为Kilobytes。

上面的例子中,我们可以看到磁盘sda以及它的各个分区的统计数据,当时统计的磁盘总TPS是39.29,下面是各个分区的TPS。(因为是瞬间 值,所以总TPS并不严格等于各个分区TPS的总和)

2. -x 参数

使用-x参数我们可以获得更多统计信息。

iostat -d -x -k 1 10
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 1.56 28.31 7.80 31.49 42.51 2.92 21.26 1.46 1.16 0.03 0.79 2.62 10.28
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 2.00 20.00 381.00 7.00 12320.00 216.00 6160.00 108.00 32.31 1.75 4.50 2.17 84.20

rrqm/s:每秒这个设备相关的读取请求有多少被Merge了(当系统调用需要读取数据的 时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge);wrqm/s:每秒这个 设备相关的写入请求有多少被Merge了。

rsec/s:每秒读取的扇区数;wsec/: 每秒写入的扇区数。r/s:The number of read requests that were issued to the device per second;w/s:The number of write requests that were issued to the device per second;

await:每一个IO请求的处理的平均时间(单位是微秒)。这里可以理解为IO的响应时 间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。

%util:在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该 设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因 为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

3. -c 参数

iostat还可以用来获取cpu部分状态值:

iostat -c 1 10
avg-cpu: %user %nice %sys %iowait %idle
1.98 0.00 0.35 11.45 86.22
avg-cpu: %user %nice %sys %iowait %idle
1.62 0.00 0.25 34.46 63.67

4. 常见用法

$iostat -d -k 1 10 #查看TPS和吞吐量信息
iostat -d -x -k 1 10 #查看设备使用率(%util)、响应时间(await)
iostat -c 1 10 #查看cpu状态

5. 实例分析

$$iostat -d -k 1 |grep sda10
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda10 60.72 18.95 71.53 395637647 1493241908
sda10 299.02 4266.67 129.41 4352 132
sda10 483.84 4589.90 4117.17 4544 4076
sda10 218.00 3360.00 100.00 3360 100
sda10 546.00 8784.00 124.00 8784 124
sda10 827.00 13232.00 136.00 13232 136

上面看到,磁盘每秒传输次数平均约400;每秒磁盘读取约5MB,写入约1MB。

iostat -d -x -k 1
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 1.56 28.31 7.84 31.50 43.65 3.16 21.82 1.58 1.19 0.03 0.80 2.61 10.29
sda 1.98 24.75 419.80 6.93 13465.35 253.47 6732.67 126.73 32.15 2.00 4.70 2.00 85.25
sda 3.06 41.84 444.90 54.08 14204.08 2048.98 7102.04 1024.49 32.57 2.10 4.21 1.85 92.24

可以看到磁盘的平均响应时间<5ms,磁盘使用率>80。磁盘响应正常,但是已经很繁忙了。

参考文献:

  1. Linux man iostat
  2. How Linux iostat computes its results
  3. Linux iostat

http://blog.csdn.net/AE86_FC/archive/2010/02/03/5284112.aspx

 

最近要对分布式集群做一些性能测试,其中一个很重要的项就是测试hadoop分布式集群在支持多磁盘轮转 写入的时候在各种磁盘配置的情况下的读写性能,如 在RAID0,RAID5和JBOD情况下的磁盘性能,所以linux下的iostat命令就在产生report的脚本中非常有用,特此记录下iostat命令的一些使用笔 记
[命令:] iostat [-c|-d] [-k] [-t] [间隔描述] [检测次数]
参 数:
-c : 仅显示cpu的状态
-d : 仅显示存储设备的状态,不可以和-c一起使用
-k : 默认显示的是读入读出的block信息,用-k可以改成KB大小来显示
-t  : 显示日期
-p device | ALL : device为某个设备或者某个分区,如果使用ALL,就表示要显示所有分区和设备的信息

显示示例:
avg-cpu:  %user   %nice    %sys %iowait   %idle
4.55    0.00    0.63    0.26   94.56

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
cciss/c0d0       30.11        68.20        67.13 1232784060 1213452142
cciss/c0d0p1      0.00         0.00         0.00       2531          2
cciss/c0d0p2     83.78        68.18        67.11 1232572011 1213204536
dm-0              1.06         0.60         4.07   10873201   73555720
dm-1             82.50        67.42        62.23 1218704309 1124966656
dm-2              0.21         0.18         0.83    3199605   14929540
dm-3              0.00         0.00         0.00        372        224

以上显示分为上下两个部 分,上半部分显示CPU的信息,下面的数 据显示存储设备的相关数据,它的数据意义如下:
tps:平均每秒钟的传送次数,与数据传输“次数”相关,非容 量
kB_read/s:启动到现在的平均读取单位
kB_wrtn/s:启动到现在的平均写入单位
kB_read:启动到现在总共 读出来的文件单位
kB_wrtn: 启动到现在总共写入的文件单位

如果想要对iostat检查多此,每次之间的间隔一定数量的秒数,这样就可以查看每几秒钟之内的io统计数 据,这对性能的测试才具有实际意义:
$> iostat -d 2 3
表示没量秒钟检查一次,一共检查三次
avg-cpu:  %user   %nice    %sys %iowait   %idle
4.55    0.00    0.63    0.26   94.56

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
cciss/c0d0       30.11        68.20        67.13 1232900288 1213456210
cciss/c0d0p1      0.00         0.00         0.00       2531          2
cciss/c0d0p2     83.78        68.19        67.11 1232688239 1213208604
dm-0              1.06         0.60         4.07   10873201   73558008
dm-1             82.50        67.42        62.23 1218820537 1124967604
dm-2              0.21         0.18         0.83    3199605   14930372
dm-3              0.00         0.00         0.00        372        224

avg-cpu:  %user   %nice    %sys %iowait   %idle
0.00    0.00    0.63    0.00   99.37

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
cciss/c0d0        1.02         0.00        63.27          0        124
cciss/c0d0p1      0.00         0.00         0.00          0          0
cciss/c0d0p2     15.82         0.00        63.27          0        124
dm-0             15.82         0.00        63.27          0        124
dm-1              0.00         0.00         0.00          0          0
dm-2              0.00         0.00         0.00          0          0
dm-3              0.00         0.00         0.00          0          0

avg-cpu:  %user   %nice    %sys %iowait   %idle
0.00    0.00    0.32    0.00   99.68

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
cciss/c0d0        3.06         0.00        26.53          0         52
cciss/c0d0p1      0.00         0.00         0.00          0          0
cciss/c0d0p2      6.63         0.00        26.53          0         52
dm-0              0.00         0.00         0.00          0          0
dm-1              6.63         0.00        26.53          0         52
dm-2              0.00         0.00         0.00          0          0
dm-3              0.00         0.00         0.00          0          0

其中每一次的统计都是上 一次的统计时间到这次的统计时间之间的统计数据

 

5. 如何查看进程 IO 读写情况?

Linux Kernel 2.6.20 以上的内核支持进程 IO 统计,可以用类似 iotop 这样的工具来监测每个进程对 IO 操作的情况,就像用 top 来实时查看进程内存、CPU 等占用情况那样。但是对于 2.6.20 以下的 Linux 内核版本就没那么幸运了,根据Stack Overflow 的这篇回帖给出的方法,VPSee 写了一个简单的 Python 脚本用来在 linux kernel < 2.6.20 下打印进程 IO 状况。

Kernel < 2.6.20

这个脚本的想法很简单,把 dmesg 的结果重定向到一个文件后再解析出来,每隔1秒钟打印一次进程 IO 读写的统计信息,执行这个脚本需要 root:

#!/usr/bin/python
# Monitoring per-process disk I/O activity
# written by http://www.vpsee.com 

import sys, os, time, signal, re

class DiskIO:
    def __init__(self, pname=None, pid=None, reads=0, writes=0):
        self.pname = pname
        self.pid = pid
        self.reads = 0
        self.writes = 0

def main():
    argc = len(sys.argv)
    if argc != 1:
        print "usage: ./iotop"
        sys.exit(0)

    if os.getuid() != 0:
        print "must be run as root"
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)
    os.system(‘echo 1 > /proc/sys/vm/block_dump‘)
    print "TASK              PID       READ      WRITE"
    while True:
        os.system(‘dmesg -c > /tmp/diskio.log‘)
        l = []
        f = open(‘/tmp/diskio.log‘, ‘r‘)
        line = f.readline()
        while line:
            m = re.match(                ‘^(\S+)\((\d+)\): (READ|WRITE) block (\d+) on (\S+)‘, line)
            if m != None:
                if not l:
                    l.append(DiskIO(m.group(1), m.group(2)))
                    line = f.readline()
                    continue
                found = False
                for item in l:
                    if item.pid == m.group(2):
                        found = True
                        if m.group(3) == "READ":
                            item.reads = item.reads + 1
                        elif m.group(3) == "WRITE":
                            item.writes = item.writes + 1
                if not found:
                    l.append(DiskIO(m.group(1), m.group(2)))
            line = f.readline()
        time.sleep(1)
        for item in l:
            print "%-10s %10s %10d %10d" %                 (item.pname, item.pid, item.reads, item.writes)

def signal_handler(signal, frame):
    os.system(‘echo 0 > /proc/sys/vm/block_dump‘)
    sys.exit(0)

if __name__=="__main__":
    main()

 

Kernel >= 2.6.20

如果想用 iotop 来实时查看进程 IO 活动状况的话,需要下载和升级新内核(2.6.20 或以上版本)。编译新内核时需要打开 TASK_DELAY_ACCT 和 TASK_IO_ACCOUNTING 选项。解压内核后进入配置界面:

# tar jxvf linux-2.6.30.5.tar.bz2
# mv linux-2.6.30.5 /usr/src/
# cd /usr/src/linux-2.6.30.5

# make menuconfig

选择 Kernel hacking –> Collect scheduler debugging info 和 Collect scheduler statistics,保存内核后编译内核:

# make; make modules; make modules_install; make install

修改 grub,确认能正确启动新内核:

# vi /boot/grub/menu.lst

出了新内核外,iotop 还需要 Python 2.5 或以上才能运行,所以如果当前 Python 是 2.4 的话需要下载和安装最新的 Python 包。这里使用源代码编译安装:

# tar jxvf Python-2.6.2.tar.bz2
# cd Python-2.6.2
# ./configure
# make; make install

别忘了下载 setuptools:

# mv setuptools-0.6c9-py2.6.egg.sh setuptools-0.6c9-py2.6.egg
# sh setuptools-0.6c9-py2.6.egg

更多信息

如果想知道更多关于 block_dump 的信息,可以看看这篇监测 Linux 进程的实时 IO 情况。使用 block_dump 的时候,最好能关掉 klogd 进程

 







































































































































































以上是关于linux wa%过高,iostat查看io状况的主要内容,如果未能解决你的问题,请参考以下文章

linux负载过高 排查方法及说明 附:Centos安装iostat

监控io性能/free命令/ps命令/查看网络状况/linux下抓包

如何查看Linux下进程的IO活动状况 00 Hey,Linux

解决linux cpu占用不高但是负载很高

找出导致Mysql机器IO过高的SQL

linux iowait过高怎么查