摘要:top 里 %CPU 只有 30%,接口却从 50ms 飙到 800ms------这种"慢"最折磨人。本文把基础四件套(top/free/iostat/ss)和进阶双剑客(perf / strace)串成一条可复用的排查链路:先定方向,再选工具,读图定位,交叉验证。所有命令均可直接复现。
0. 为什么不能"上来就 top"
很多同学排障的第一反应是 top,然后看着 %CPU 不高就下结论"CPU 没问题"。但"慢"和"CPU 满"根本不是一回事:
- 延迟可能耗在磁盘 IO 等待(iowait 高,但 CPU 在闲等);
- 可能耗在被换页的内存压力(free 变 0、开始 swap);
- 也可能耗在某个卡住的网络 connect / read(时间根本不体现在 CPU 占用里)。
方向判错,后面再怎么调优都是白做。所以第一步永远是定方向,而不是盲调。
1. 总览:排查链路一张图
scss
top / htop → 整机概览,看 load、%wa、si/so
↓ 定方向
CPU? / 内存? / IO?
↓ 选工具
perf(CPU热点) strace(syscall阻塞) iostat(磁盘) ss(网络)
↓ 出图
火焰图 / strace -T 高耗时调用
↓ 交叉验证
iostat ↔ pidstat ↔ free/vmstat 互相印证
↓ 结论
改代码 / 调参数 / 扩容
工具分工边界:
| 工具 | 擅长 | 看什么 |
|---|---|---|
perf |
CPU 热点、内核态开销(on-CPU) | 哪个函数最占 CPU |
strace |
系统调用级追踪 | 进程卡在哪个 syscall(IO/锁/信号) |
iostat / ss |
系统级 IO / 网络 | 磁盘 %util、连接数分布 |
2. 基础四件套(先定方向,5 秒出结论)
bash
# CPU / 负载
top -b -n 1 | head -20
mpstat 1 3 # 看每核,重点盯 %iowait
# 内存(看 available,别只看 free)
free -h && vmstat 1 5 # si/so 不为 0 = 内存开始换页
# 磁盘
iostat -x 1 5 # %util>70% 忙,await>10ms 慢
# 网络
ss -s # 连接数统计
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn # 状态分布
判定口诀:
load / CPU核数 > 0.7才健康;
free -h看 available,不是 free------Linux 会用空闲内存做 cache;
vmstat的si/so > 0或%wa > 20%,基本能锁定内存/磁盘方向。
3. CPU 瓶颈:perf 抓热点
bash
# 安装(版本最好与内核一致)
apt install -y linux-tools-common linux-tools-$(uname -r) strace
# 系统范围采样 30s,99Hz 是社区惯例(避开整百共振)
perf record -F 99 -ag -- sleep 30
# 只看某个进程
perf record -F 99 -p $PID -g -- sleep 30
# 交互式看热点
perf report
perf top -p $PID
踩坑:
-F别用 999,-F 99足够,过高会放大自身开销、污染结果。
4. 内存瓶颈:别只看 free
bash
# 量化缓存与缺页(major-faults 偏高 = 已逼出磁盘换入)
perf stat -e cache-misses,cache-references,page-faults,major-faults \
-p $PID -- sleep 10
# 定位是谁在触发缺页
perf record -e page-faults -ag -p $PID -- sleep 10
# 系统级印证
free -h && vmstat 1 5
cat /proc/meminfo
major-faults 显著偏高往往意味着内存压力已经逼出 IO;cache-misses 高说明热点数据没留在 CPU 缓存。深度泄漏分析还需 jemalloc/jeprof、Valgrind 等,本文不展开。
5. IO 瓶颈:strace 看"卡在哪个调用"
bash
# 只看文件/网络调用的耗时(定位阻塞点)
strace -Ttt -e trace=file,network -f -p $PID
# 汇总统计更快
strace -c -f -p $PID -- sleep 5
# 系统级印证
iostat -x 1 && pidstat -d 1
-T 标出的高耗时 read/write/connect 就是阻塞点。比如某 connect 每次几百毫秒,问题大概率在网络或下游服务,而不是本机 CPU。
6. 综合实战:接口变慢决策树
bash
# 1) 定方向
top -b -n 1 | head -20 && mpstat 1 3
# 2) CPU 热点
perf record -F 99 -ag -p $PID -- sleep 20
# 3) syscall 层
strace -Ttt -e trace=file,network -f -p $PID -- sleep 5
# 4) 内存 / 缓存
perf stat -e cache-misses,page-faults -p $PID -- sleep 10
free -h && vmstat 1 5
典型结论:
- perf 显示某函数占 CPU 最高 → 改代码优化;
strace显示connect高耗时 → 排查下游/网络;
vmstat的si/so不为 0 → 加内存或查泄漏。
7. 避坑清单(生产环境必看)
- strace 通过 ptrace 显著拖慢目标进程 :生产慎用、避免长时间 attach;统计优先用
-c,拿完数据立刻退出。
- perf 频率并非越高越好 :
-F 99是惯例。
- 权限约束 :
cat /proc/sys/kernel/perf_event_paranoid取值越高限制越严(常见默认 2~4),内核态/整机数据需要CAP_PERFMON/CAP_SYS_ADMIN;容器内需放开 securityContext。
- 采样要覆盖真实业务高峰,别把偶发抖动当稳定根因。
8. 一页速查表
| 方向 | 工具 | 关键命令 | 判读 |
|---|---|---|---|
| CPU | perf | perf record -F 99 -ag / perf top |
热点函数占用 |
| 内存 | free/vmstat | free -h / vmstat 1 |
available<10%、si/so>0 |
| 内存 | perf | perf stat -e page-faults |
major-faults 高 |
| 磁盘 | iostat | iostat -x 1 |
%util>70%、await>10ms |
| 网络 | ss | ss -ant |
TIME-WAIT/CLOSE-WAIT 过多 |
| syscall | strace | strace -Ttt -e trace=file,network -p |
高耗时 read/write/connect |
结论 :排查"慢"的核心不是工具多熟,而是先定方向、再选工具、读图定位、交叉验证这条链路走稳。把这套命令和决策树收进你的排查剧本,下次告警来了就能少绕弯路。