🐧 第07章 · 性能监控

top vmstat iostat sar mpstat

性能监控

服务明明"没死"却越来越慢,到底卡在哪?性能问题绕不开四个资源:CPU、内存、磁盘 I/O、网络。这一章教你用 top、vmstat、mpstat、iostat、sar 定位瓶颈,并结合本机的 Prometheus 监控方案讲一讲"长期观测"。

性能四要素

资源 主要命令 关注指标
CPU top、mpstat us/sy/id/wa、每核占用
内存 free、vmstat available、si/so(swap)
磁盘 I/O iostat、iotop %util、await、r/s、w/s
网络 ss、sar -n、iftop 连接数、每秒收发

易错 性能排查最忌讳"盯着一个指标死磕"。负载高不一定是 CPU 忙——很可能在等磁盘 (wa) 或排队网络。正确做法是四个资源同时看一眼,先确定"到底谁忙"。

top:第一印象

top 是实时全貌,进入后按 P(CPU 排序)、M(内存排序)、q(退出):

top                    # 交互
top -bn1 | head -25    # 批处理单次输出,适合记到日志

%Cpu 一行的关键字段:us(用户态)、sy(系统态/内核)、id(空闲)、wa(等待磁盘 I/O,越大说明磁盘是瓶颈)、st(被宿主机偷走的,虚机才有)。

提示 wa(iowait)高是"磁盘慢"的典型信号。us 高是应用吃 CPU,sy 高是系统调用/内核忙(常见于频繁网络收发或文件读写)。

vmstat:采样看趋势

单次 top 是瞬间截图,vmstat 能连续采样看趋势(性能问题常是间歇性的):

vmstat 2 10             # 每 2 秒一次,共 10 次
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     0   ...   ...   ...    0   0    0    0   ... .. 20 10 68  2  0

关键列:r(运行队列,>CPU 核数即过载)、b(阻塞队列,>0 说明有 I/O 卡住)、wa(iowait)、bi/bo(每秒块读/写)、si/so(swap 换入/换出,非零即内存吃紧)。

易错 r 是"排队等 CPU 的任务数",判断过载要除以核数(本机 4 核,r 长期 >4 才算 CPU 饱和)。b 长期非零则多半是磁盘 I/O 瓶颈,别误判成 CPU。

mpstat:CPU 用在哪

多核机器上某几核被打满而整体不高,用 mpstat -P 按核看:

mpstat -P ALL 2        # 每 2 秒输出每个核的状态
mpstat 2               # 所有核平均

易错 Node/PHP 应用大多是单线程,mpstat -P ALL 能看到"只有核 0 忙碌、其余空闲",这类无法靠加核解决,要加进程数(cluster)或拆服务。本机 Node 默认单进程,正是此理。

iostat:磁盘是否瓶颈

iostat 是磁盘 I/O 专项工具(sysstat 包,需要 apt install sysstat):

iostat -x 2            # 每 2 秒,列详细信息(含 %util、await)
iostat -xz 2           # -z 只显示有活动的设备,更干净

重点关注列:%util(磁盘繁忙百分比,接近 100 说明 I/O 饱和)、await(平均响应毫秒,越大越慢)、r/s/w/s(每秒读/写次)、rMB/s/wMB/s(吞吐)。

易错 %util=100 并不一定代表"慢",它只说明磁盘一直在忙。真正的磁盘性能差参考 await(单次 I/O 响应时间)。SSD 上 await 应个位数毫秒,机械盘可能几十毫秒;await 持续过高说明排队严重。

sar:历史与定时采集

sar 来自 sysstat,能看某时段的历史(默认靠 cron 记录)——这正适合"问题发生在凌晨但你没在场"的场景:

sar -u     # CPU 使用率
sar -r     # 内存
sar -b     # 块 I/O
sar -n DEV # 网络
sar -u 1 5 # 每 1 秒采样 5 次
# sysstat 会通过 cron 每天记录,默认 7 天;可查某天数据
sar -u -f /var/log/sysstat/sa06     # 找 06 号的历史文件

易错 sar 的日/周/月数据需要 /etc/cron.d/sysstat 里的定时任务持续写入,默认保留 7 天。若用 systemctl 管理服务器,确认 sysstat 服务及 cron 正常,否则看不到历史。

长期监控:Prometheus + node-exporter

短时命令看不到的"缓慢爬升""深夜偶发",要交给监控。本机已部署 Prometheus 体系:

systemctl status prometheus                # 时间序列数据库(9090)
systemctl status prometheus-node-exporter  # 采集主机指标(9100)
ss -tlnp | grep 9090                      # 确认 Prometheus 在监听

node-exporter 暴露大量主机指标(CPU、内存、磁盘、网络、文件描述符),Prometheus 定时抓取并落库,Grafana 画图、设告警。它的关键指标包括:

  • node_cpu_seconds_total —— CPU 使用;
  • node_memory_MemAvailable_bytes —— 可用内存;
  • node_filesystem_avail_bytes —— 可用磁盘;
  • node_load1/5/15 —— 平均负载。

易错 node-exporter 默认绑定 9100,若对外暴露需用防火墙限制来源(见第 8 章)。真实告警不要在 Prometheus 里写死一个"CPU>80"——要结合基线(比如 irate 计算瞬时速率)判断。这类规则属运维进阶,本章先建立"有监控、能看趋势"的意识。

性能基线:先知道"正常是多少"

性能监控的终极目标是建立基线。没有基线,任何数字都无参照。建议:

  1. 记录本机常态:空载 us%、id%、wa%,free 的 available,磁盘 %util;
  2. 用 sar/Prometheus 存历史,形成"正常区间";
  3. 异常来临对比基线,才能判断"是异常还是本来如此"。
# 日常随手记一条基线
echo "[$(date)] $(uptime) | $(free -h | awk 'NR==2{print $3}') used | $(iostat -x 1 1 | grep sda | awk '{print $14}') %util" >> /var/log/system_baseline.log

案例:Node 应用响应慢的排查

top -bn1 | head -20                      # CPU/wa 一眼看谁忙
mpstat -P ALL 2                          # 是否单核打满
free -h                                  # 内存
vmstat 1 5                               # r/b/si/so
iostat -x 2                              # 是否磁盘瓶颈
ss -s                                    # socket 概览(是否连接堆积)

若 us 接近 100 → 应用代码吃 CPU,去优化;若 wa 高 → 磁盘慢(换 SSD/加缓存);若 si/so 非零 → 内存吃紧。

易错点

  • 只盯一个指标:四要素要同时看,确定瓶颈在谁。
  • r 不除核数判断过载:本机 4 核,r>4 才算 CPU 饱和。
  • %util=100 就判磁盘死:还要看 await 是否真的高。
  • 无基线不设告警:随手写死阈值会误报或漏报。

相关命令

top、htop、vmstat、mpstat、iostat、sar、iotop、ss、free、iftop、uptime。