场景引入:服务器变慢了怎么办
线上服务器突然变慢了,用户反馈页面加载要十几秒。你SSH上去第一件事做什么?我见过不少同事第一反应是 top 看看CPU。但CPU不高呢?内存还有很多呢?那问题在哪?大概率是磁盘I/O(Input/Output,输入输出)成了瓶颈。
我遇到过一个真实案例:一个数据分析任务跑得好好的,突然慢了10倍。top看CPU只有20%,free看内存还剩8GB,但vmstat里的wa(等待I/O)列高达60%。再用iostat一看,磁盘util(使用率)100%、await(平均I/O等待时间)超过500毫秒。原来是有个同事同时运行了一个大文件压缩任务,把磁盘I/O打满了。这就是iostat和vmstat的典型应用场景。
vmstat:系统整体视图
vmstat(virtual memory statistics)是一个轻量级的全能系统监控工具。它能同时展示进程、内存、交换分区、I/O、系统、CPU六个维度的信息。一次vmstat输出,能快速判断系统瓶颈在哪个环节。
基本用法:
# 查看系统总体状态,每秒采样一次,共采样5次
vmstat 1 5
输出结果分为几个部分,每个列都有明确的含义。
procs部分的r列(running,运行队列中进程数)和b列(blocked,阻塞中的进程数)。如果r列长期大于CPU核数,说明CPU不够用了。如果b列持续不为0,说明有进程在等待I/O,磁盘可能是瓶颈。
memory部分的swpd列(swapped,已使用的交换内存大小)如果很高,说明物理内存紧张。free列(空闲内存)如果接近0,也需要关注。
swap部分的si(swap in,从磁盘交换到内存的数据量)和so(swap out,从内存交换到磁盘的数据量)。这两个值如果持续大于0,说明内存严重不足,系统正在频繁换页,性能会急剧下降。
io部分的bi(blocks in,从块设备读入的数据量)和bo(blocks out,写入块设备的数据量)。这两个值可以初步判断磁盘读写是否繁忙。
system部分的in(interrupts,中断数)和cs(context switches,上下文切换次数)。cs过高可能意味着系统在频繁切换进程,也可能是大量短生命周期进程在运行。
cpu部分的us(user,用户态CPU使用率)、sy(system,系统态CPU使用率)、id(idle,空闲率)、wa(wait,I/O等待率)、st(stolen,被虚拟机偷走的CPU)。wa是判断I/O瓶颈的关键。
vmstat实战:定位瓶颈类型
我总结了一套vmstat快速定位方法。首先在终端运行 vmstat 1 5:
# 每1秒采样一次vmstat,共采集5次,用于快速定位系统瓶颈
vmstat 1 5
假设输出如下(人工模拟):
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 102400 12456 20480 524288 0 1 10 20 100 2000 5 3 90 2 0
5 0 102400 12456 20480 524288 0 0 10 20 200 5000 30 20 45 5 0
8 0 102400 12456 20480 524288 0 0 10 20 300 8000 50 30 15 5 0
看r列从2升到8,但CPU核数只有4,说明进程在排队等待CPU。再看us+sy加起来80%了,id只有15%,wa只有5%。结论是:CPU瓶颈。
再看另一个场景:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 2 102400 12456 20480 524288 0 0 2000 1000 150 1000 10 5 20 65 0
0 3 102400 12456 20480 524288 0 0 3000 2000 180 1200 8 4 5 83 0
1 3 102400 12456 20480 524288 0 0 2500 1500 160 1100 9 5 10 76 0
b列持续在2到3,wa(I/O等待)高达65%到83%。这就是典型的I/O瓶颈。CPU大部分时间在等待磁盘,所以CPU自身利用率很低。
再看最后一个场景:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 512000 5000 10240 204800 200 150 500 1000 200 3000 10 5 60 25 0
3 0 612000 4000 10240 204800 300 200 600 1200 220 3200 12 6 50 32 0
si和so都大于0,意味着系统在频繁地进行内存换页。自由内存也很低。这是内存不足的典型表现。解决方法是加内存或者排查内存泄漏。
iostat:磁盘IO的详细诊断
vmstat告诉你"有I/O瓶颈",但具体是哪个磁盘、I/O有没有排队、响应时间多少,就需要iostat登场了。
安装iostat需要sysstat包:
# 在Ubuntu/Debian上安装sysstat包以获取iostat命令
sudo apt-get install sysstat
# 在CentOS/RHEL上安装
sudo yum install sysstat
基本用法看汇总信息:
# 查看磁盘I/O统计,每秒采样,共3次
iostat 1 3
输出包含CPU利用率和设备I/O统计两部分。关键指标在设备部分:
- ·tps(transactions per second,每秒I/O请求数)
- ·kB_read/s和kB_wrtn/s(每秒读写千字节数)
- ·await(average I/O wait time,平均每次I/O请求等待时间,单位毫秒)。如果await大于几十毫秒(机械盘)或几毫秒(SSD),说明I/O有排队。
- ·svctm(average service time,平均I/O服务时间,已废弃但仍显示)
- ·%util(I/O利用率,百分比)。如果%util接近100%,说明磁盘已经满负荷运转。
iostat -x:详细输出
真正看磁盘性能,一定要加 -x 参数,它会输出更详细的指标:
# 显示扩展的磁盘I/O统计信息,每秒采样,共3次
iostat -x 1 3
重点关注几个指标:
rrqm/s和wrqm/s(每秒合并的读/写请求数)。Linux内核会把相邻的小请求合并成大请求来提高效率。如果这个值很高,说明你的应用在产生大量小I/O(比如随机读写数据库文件)。
r_await和w_await(平均读/写等待时间)。分开看能知道是读慢还是写慢。我曾经遇到一个MySQL慢查询场景,r_await高达300ms而w_await只有2ms,说明磁盘读性能是瓶颈。
aqu-sz(average queue size,平均I/O队列长度)。这个值持续大于0说明I/O请求在排队。
一个典型的高负载场景:
# 查看磁盘的扩展I/O统计,重点关注await和%util指标
iostat -x -d sda 2 3
如果看到%util=100%且await>100ms,说明磁盘已经不堪重负了。
我在腾讯云轻量服务器上跑过一个实际案例。一台机器跑MySQL和Nginx,用户反映网站间歇性慢。iostat -x一看,数据盘%util经常冲到90%以上,await在200ms左右徘徊。原因是一台低配云服务器,磁盘IOPS(每秒输入输出次数)上限本来就不高,MySQL的随机读写把IOPS打满了。解决方案是把MySQL数据文件和Nginx日志文件放到不同的云盘上,分散I/O压力。
CPU瓶颈、I/O瓶颈、内存瓶颈的定位方法
我总结了一个简单有效的排查流程:
第一步,跑 vmstat 1 5 快速看全貌。如果wa高,去查I/O。如果us+sy高且r列大于CPU核数,查CPU。如果si/so持续非零,查内存。
第二步,定位到I/O瓶颈后用 iostat -x 1 3 锁定具体磁盘。如果是CPU瓶颈用 mpstat -P ALL 1 3 看各核负载分布。如果是内存瓶颈用 free -h 和 top 排序内存看具体进程。
第三步,定位到具体进程。top 按 x 高亮排序列,按 u 输入用户名只看某用户进程。或者用 ps aux --sort=-%mem | head 查看内存消耗最高的进程。
我遇到过一个有趣的案例。vmstat显示wa高,iostat显示sda的%util高,但top里任何一个进程CPU都不高。最终发现是一个crontab配置错误,每小时全量备份数据库导致I/O尖刺。这告诉我们,性能排查不只看"有问题时",还要看"什么触发了问题"。
安全提醒
运行性能监控命令时要注意几点。第一,iostat 1 0 这种写法会导致无限采样,终端会持续刷屏,如果忘记关掉,可能会占用SSH会话导致无法操作其他命令。养成好习惯,加上采样次数 iostat 1 5。第二,在某些老旧系统上,iostat的%util计算方式不同,对SSD(固态硬盘)可能不准确。现代SSD可以同时处理多个请求,%util显示100%不代表真的满了,需要结合await判断。第三,性能分析不要在业务高峰期做大量的连续采样,本身也会产生一定的CPU开销。虽然很小,但在高负载机器上也是额外负担。
小结
vmstat是侦查兵,快速告诉你哪个环节出问题。iostat是工兵,精确定位磁盘的具体问题。两把刷子配合使用,大部分性能瓶颈都能快速定位。下次再遇到"服务器变慢了"的问题,别只盯着top看CPU了。跑一遍vmstat和iostat,三分钟内你就能判断出是CPU不够、内存不足还是磁盘背锅。