如何读取vmstat的输出
让我们先看一个vmstat的例子。使用下面的命令,每隔5秒钟输出一个新行
$ vmstat 5
procs ----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 2632 25728 23176 740244 0 0 527 521 11 3 10 1 86 3
0 0 2632 27808 23180 738248 0 0 2 430 222 66 2 0 97 0
报告的第一行值显示的是从系统启动以来的平均值。第二行显示的是当前值,后面每五秒显示一行。显示的列按标题分组。
procs
r列显示有多少进程正在等待cpu时间。b列显示有多少进程处于不可中断的睡眠状态,通常说明这些进程正在等待I/O(磁盘、网络、用户输入等等)。
memory
swpd列显示有多少块被交换到磁盘(分页)。剩余的三列分别显示有多少空闲块(未使用的块),有多少块被用于缓冲区,有多少块被用于操作系统的高速缓存。
swap
这些列显示交换区的活动:操作系统每秒有多少块换入(从磁盘到交换区)换出(从交换区到磁盘)。对这些值的监控比对swpd列要重要的多。
我们可能看到在大部分时间里si和so在都是0,而且我们肯定不希望看到每秒多于10块。突然的增高也是不利的。
io
这些列显示每秒有多少块从块设备读入(bi)和写出(bo)。这通常反映磁盘I/O。
system
这些列显示每秒有多少次中断(in)和每秒多少次上下文切换(cs)。
cpu
这些列分别显示运行用户(非核心)代码、运行系统(核心)代码、空闲和等待I/O的cpu时间占整个cpu时间的百分比。
vmstat的输出是依赖于系统的,所以如果你的输出和我们显示的不同,应该读你的vmstat(8)系统帮助页。重要的一点是:内存、交换区和I/O统计都是以块而不是以字节为单位。在Linux中,块大小一般是1,024字节。
如何读取iostat的输出
缺省时,iostat显示一些与vmstat相同的cpu使用信息。我们通常只对I/O统计感兴趣,所以使用下面的命令只显示扩展设备统计:
$ iostat -dx 5
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 1.6 2.8 2.5 1.8 138.8 36.9 40.7 0.1 23.2 6.0 2.6
与vmstat相似,报告的第一行显示的是从系统启动以来的平均值。后面显示随时间变化的平均值。每个设备一行。
有很多选项用来显示或隐藏某列。我们这里显示的列如下:
rrqm/s and wrqm/s
每秒合并读写请求排队数。“合并”指的是操作系统把多个逻辑请求组成一个对实际设备的请求。
r/s and w/s
每秒发送给设备的读写请求数。
rsec/s and wsec/s
每秒读写的扇区数。有些系统还输出rkB/s和wkB/s,每秒读写的千字节数。
avgrq-sz
扇区中的请求大小。
avgqu-sz
在设备队列中等待的请求数。
await
相应请求所需要的毫秒数,包括排队时间和服务时间。不幸的是,iostat并不分别显示读请求和写请求的时间,而读写数有很大的不同,不应该一起平均。但是,你可以记录下高I/O读等待,因为写经常会被缓存而读通常需要从磁盘直接读取。
svctm
为请求提供服务所花费的毫秒数,从开始到结束,包括排队所花的时间和设备实际完成请求所花的时间。
%util
发出请求期间的CPU时间百分比。正如其名字所表示出的,这个数值真正显示出对设备的利用情况,因为当这个值接近100%时,设备处于饱和状态。
你可以从这些输出推导出机器I/O子系统的一些情况。一个重要的指标是并发请求服务数。由于读写数是以每秒为单位而服务时间的单位是毫秒,下面的公式表示设备正在服务的并发请求数:
concurrency = (r/s + w/s) * (svctm/1000)
(计算并发的另外一种方式是通过平均队列大小、服务时间和平均等待:(avuqu_sz * svctm)/await)
下面是一个iostat的输出示例:
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 105 311 298 820 3236 9052 10 127 113 9 96
将 相应的数值代入公式得到的并发数是9.6(如果你做这个计算,得到的是10左右,因为我们在这里对iostat的输出进行了四舍五入处理。因此,实际的结 果是9.6)。这说明在每个采样的时间间隔内,设备为9.6个请求服务。这个例子是从一个10块硬盘组成的RAID 10 卷得到,因此操作系统在这个设备上有很好的为并行请求的服务。另一方面,下面的例子显示对设备的串行请求:
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdc 81 0 280 0 3164 0 11 2 7 3 99
从并发公式得出此设备每秒只处理一个请求。两个设备都接近满负荷工作,但是它们的性能却有很大的差别。如果你的设备在始终都很繁忙,就像这个例子显示的,你应该检查并发,并且看并发数是否接近设备所包含的物理硬盘数。较小的比值可能预示着存在问题。
一个CPU密集的机器
CPU密集服务器的vmstat输出通常显示us列值较高,表示运行非核心代码所花费的时间。在大多数情况下,也会有很多进程排队等待CPU时间(r列所显示的)。下面是一个例子:
$ vmstat 5
procs ----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
10 2 740880 19256 46068 13719952 0 0 2788 11047 1423 14508 89 4 4 3
11 0 740880 19692 46144 13702944 0 0 2907 14073 1504 23045 90 5 2 3
7 1 740880 20460 46264 13683852 0 0 3554 15567 1513 24182 88 5 3 3
10 2 740880 22292 46324 13670396 0 0 2640 16351 1520 17436 88 4 4 3
注意这里同时有很多的上下文切换(cs列)。上下文切换指的是操作系统停止一个正在运行的进程并用其它进程替换它。
如果你在同一个机器看iostat的输出(再次忽略表示自启动以来平均值的第一行),可以看到磁盘的利用率不到50%:
$ iostat -dx 5
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 0 3859 54 458 2063 34546 71 3 6 1 47
dm-0 0 0 54 4316 2063 34546 9 18 4 0 47
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 0 2898 52 363 1767 26090 67 3 7 1 45
dm-0 0 0 52 3261 1767 26090 8 15 5 0 45
这个机器不是I/O密集的,但仍然有一定数量的I/O,这些I/O通常不是数据库服务产生的。另一方面,一个web服务器会消耗大量的CPU资源但是很少量的I/O,所以web服务器的输出一般不像这个例子。
一个I/O密集的机器
在一个I/O密集的负载中,CPU会花大量的时间等待完成I/O请求。这时vmstat会显示有大量进程处于不可中断的睡眠状态(b列),wa列也会有较高的值。如下面的例子:
$ vmstat 5
procs ----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
5 7 740632 22684 43212 13466436 0 0 6738 17222 1738 16648 19 3 15 63
5 7 740632 22748 43396 13465436 0 0 6150 17025 1731 16713 18 4 21 58
1 8 740632 22380 43416 13464192 0 0 4582 21820 1693 15211 16 4 24 56
5 6 740632 22116 43512 13463484 0 0 5955 21158 1732 16187 17 4 23 56
这个机器的iostat输出显示磁盘完全饱和:
$ iostat -dx 5
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 0 5396 202 626 7319 48187 66 12 14 1 101
dm-0 0 0 202 6016 7319 48130 8 57 9 0 101
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 0 5810 184 665 6441 51825 68 11 13 1 102
dm-0 0 0 183 6477 6441 51817 8 54 7 0 102
%util的值可能因为四舍五入的原因大于100%。
I/O密集的机器说明了什么呢?如果对写请求由足够的缓存能力,一般来说,但不一定,意味着磁盘跟不上读请求,即使机器做大量的写。这可能与直觉相反。考虑读写的本质:
. 写请求既可以同步也可以被缓存。它们可以被缓存在我们在本书其它部分讨论到的任何级别:操作系统、RAID控制器等等。
. 读请求本质上同步的。可能为了一个需要某些数据的程序发出一个异步的预获取(提前读)请求。但是更为普通的做法是在程序可以继续工作之前为其找到它们需要的数据。这就强制同步读请求:程序必须等待请求完成。
可以这样想:你可能发出一个写请求,先被写入缓冲区里在以后某个时间完成。你甚至可以在一秒钟里发出许多这样的请求。如果缓冲区正常工作并且有足够的空间,那么每个请求可以很快完成,实际被写到物理磁盘上时可以为了提高效率而批量处理和重新排序。
但是,对于读却无法这样做———无论请求多少多小,都不可能这样响应磁盘,“这有你要的数据,我将以后读取。”这就是为什么通常读会造成I/O等待。
一个交换密集的机器
一个交换密集的机器,swpd列的值可能高也可能低。但是,你将会看到si和so列有很高的值,这是你不想看到的。下面的例子显示在一个存在大量交换的机器上vmstat的类似输出:
$ vmstat 5
procs ----------memory------------- ---swap---- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 10 3794292 24436 27076 14412764 19853 9781 57874 9833 4084 8339 6 14 58 22
4 11 3797936 21268 27068 14519324 15913 30870 40513 30924 3600 7191 6 11 36 47
0 37 3847364 20764 27112 14547112 171 38815 22358 39146 2417 4640 6 8 9 77
一个空闲机器
出于完整性的目的,这里给出在一个空闲机器上vmstat的输出。注意这里没有正在运行或被阻断的进程,idle列显示CPU100%空闲。这个例子取自一台运行Red Hat Enterprise Linux 5的机器,并且显示了st列,表示从虚拟机“偷”的时间。
$ vmstat 5
procs ------------memory---------- ---swap-- ----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 108 492556 6768 360092 0 0 345 209 2 65 2 0 97 1 0
0 0 108 492556 6772 360088 0 0 0 14 357 19 0 0 100 0 0
0 0 108 492556 6776 360084 0 0 0 6 355 16 0 0 100 0 0