Linux 服务器性能排查手册:CPU、内存、磁盘 IO、网络四大瓶颈定位
运维学习路线系列 · 阶段二 系统进阶 · 第 5 篇(长篇 · 本阶段核心)
适用环境:Ubuntu 24.04 LTS,sysstat 工具集,普通用户(有 sudo)
阅读前提:阶段一全部 + S2-01/S2-02
前言:老板说"服务器好卡",从哪查起?
运维日常最高频的一句话不是"部署一下",而是"服务器好卡,你看看"。卡 = 资源瓶颈,但资源有四种(CPU、内存、磁盘 IO、网络),先查哪个?查到之后看哪个指标下结论?
这篇给你一张决策树 和四大瓶颈各自的"确认三步"。学完的标志:拿到一台"卡"的机器,5 分钟内说出瓶颈在哪、根因大概是谁。
一、总纲:60 秒三板斧
bash
uptime # 负载与运行时长
top # 全景热力图
dmesg -T | tail -30 # 有没有 OOM / IO error / 硬件报错(最容易被忽略的一步)
1.1 先搞懂 load average
uptime
14:30:00 up 10 days, load average: 4.2, 3.8, 3.1
└─依次是 1/5/15 分钟平均负载
负载 = 正在运行 + 不可中断等待(D 状态)的进程数(S1-06 的知识闭环)。判断标准:
| 负载 vs CPU 核数 | 结论 |
|---|---|
| < 核数(4 核 < 4.0) | 正常,排队长短不代表故障 |
| ≈ 核数 ×1~2 | 繁忙但可控,持续观察 |
| > 核数 ×2,且 15 分钟也高 | 过载,需要定位瓶颈 |
🚨 两个经典误读:① 4 核机器负载 3.5 不算故障;② 负载高 ≠ CPU 高 ------D 状态(等磁盘)也计入负载。负载 10 但 CPU 空闲 90%,瓶颈八成在磁盘。负载是"症状",不是"诊断"。
1.2 top 头部读法(对照 S1-06,这次读全)
%Cpu(s): 2.3 us, 1.1 sy, 0.0 ni, 90.2 id, 6.1 wa, 0.0 hi, 0.3 si, 0.0 st
↑用户态 ↑内核态 ↑空闲 ↑IO等 ↑硬中断 ↑软中断
| 指标 | 健康值 | 超标的含义 |
|---|---|---|
| us | <70% | 应用在烧 CPU:业务计算/死循环/序列化 |
| sy | <30% | 内核态烧:系统调用频繁、上下文切换、锁竞争 |
| wa(iowait) | <5% | >20% 基本实锤磁盘瓶颈 |
| si/hi | 低 | 网络/驱动中断风暴 |
| st | 0 | >0 = 宿主机超卖(云上虚拟机被邻居挤了) |
四个数字(us / sy / wa / st)就是四大瓶颈的方向舵:us→CPU 线,wa→IO 线,si 高→网络线,其余进内存线。
二、CPU 瓶颈线
确认三步 :top 看 us/sy → 按 1 看核间分布 → pidstat 找元凶。
bash
# 进程级 CPU 排名与波动
pidstat -u 2 3 # 每 2 秒采样 3 次(比 top 的瞬时值靠谱)
pidstat -u -p 1234 2 # 盯单个进程
# 核间分布不均?(一核打满、其余闲着)= 单线程瓶颈或中断都落在一个核
top 按 1;mpstat -P ALL 2
# 上下文切换风暴(sy 高时的帮凶)
vmstat 2 # 看 cs 列(每秒切换数,十万级+异常)与 r 列(运行队列)
pidstat -w 2 # 看自愿(cswch)/非自愿(nvcswch)切换谁最多
# CPU 究竟花在哪(sy 高时用)
sudo perf top # 内核态热点函数一览
结论模板:us 高 pidstat 锁进程 → 交给应用(慢查询/死循环/加机器);sy 高查上下文切换与锁;一核独热 = 单线程瓶颈,加机器不如优化串行点。
三、内存瓶颈线
确认三步 :free -h 看真实可用 → dmesg 查 OOM 历史 → 定位大户。
bash
free -h
# total used free buff/cache available
# Mem: 7.7G 5.1G 200M 2.4G 2.3G
# ↑ 看这列!free 少≠内存不足
- available 才是真实余量 (Linux 会把闲内存拿去做缓存,应用要用随时归还);free 200M 但 available 2.3G = 健康,别报假警;
- available 长期 <10% 且在下滑 → 内存压力;
- swap 用了且
si/so(vmstat)持续非零 → 在用磁盘冒充内存,性能雪上加霜。
bash
sudo dmesg -T | grep -i "out of memory" # 有输出=发生过 OOM,看谁的尸体在日志里
sudo journalctl -k | grep -i killed-process
ps aux --sort=-%mem | head -8 # 内存大户排名
# 更细:pmap -x 1234 | tail -5 # 单进程内存构成(RSS 映射)
smem -rk | head -10 # 按 PSS 算真实占用(RSS 有共享页重复计算)
🚨 OOM 特征:进程"莫名消失"、systemctl status 显示 OOMKilled(呼应 S5-04 Docker 里容器被杀)。找到 dmesg 里的 [ pid ] 就锁定了肇事进程。
四、磁盘 IO 瓶颈线(wa 高走这条)
确认三步 :iostat -x 看利用率与等待 → 找狂读写的进程 → 定位文件。
bash
iostat -x 2 3 # 扩展统计,每 2 秒一次
# Device r/s w/s rkB/s wkB/s r_await w_await %util
# sda 120 800 2.0M 50.0M 45.0 120.0 98.5
# ↑await:毫秒级等待 ↑利用率
| 指标 | 阈值 | 含义 |
|---|---|---|
| %util | >80% 持续 | 设备基本满转(SSD 并发下可 >100%,看 await 更准) |
| await | HDD >20ms / SSD >10ms 持续 | 每次读写等待时间,最能代表"慢" |
| r/s + w/s | 疯狂 | IOPS 型压力 |
bash
# 谁在打磁盘:iotat 进程级 IO
sudo iotop -oP # 只显示有 IO 的进程(-P 看线程/进程聚合)
sudo pidstat -d 2 3 # 无 iotop 时的替代
# 在写什么文件(进程级不够时上大招)
sudo cat /proc/$(pgrep -f 'mysqld' | head -1)/io # 单进程累计 IO
sudo lsof -p 1234 | grep -E "(REG|DIR)" | head # 它打开着哪些文件
# 或 fatsnoop/bcc 一类 eBPF 工具(进阶可选)
典型根因:MySQL 没走索引狂刷盘、日志刷太狠没批量、备份任务撞高峰、swap 抖动(内存问题伪装成 IO 问题------so/si 一起看)。
五、网络瓶颈线
确认三步:重传/丢包 → 连接状态堆积 → 带宽。
bash
# 重传统计(越高=链路质量越差)
nstat -az | grep -E "RetransSegs|OutSegs"
# 或 ss -ti | head 看 rto/rtt
# 连接状态堆积:TIME_WAIT 几万条是"短连接风暴",CLOSE_WAIT 大量=应用不关连接(代码 bug)
ss -s
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
# 带宽:iftop / nload 看实时流量
sudo apt install iftop -y && sudo iftop -i eth0
sar -n DEV 2 5 # sysstat:历史与实时网卡吞吐
ethtool eth0 | grep Speed # 确认协商速率(千兆网卡协商成百兆=经典坑)
| 症状 | 诊断 |
|---|---|
| TIME_WAIT 海量但业务正常 | 短连接太多,考虑连接池/长连接 |
| CLOSE_WAIT 持续增长 | 应用没 close(),找开发 |
| 重传率 >1% | 网络质量,S2-02 的 mtr/tcpdump 路线 |
| 带宽打满运营商上限 | 加限流/CDN/升带宽 |
六、决策树(全图收尾)
uptime + top 三板斧
├─ 有 OOM/dmesg 报错? ──→ 内存线:free → dmesg → ps 排名
├─ wa 高? ────────────→ IO 线:iostat -x → iotop → 定位文件
├─ us/sy 高? ─────────→ CPU 线:pidstat → vmstat 切换 → perf top
├─ si 高 / 连接异常? ──→ 网络线:ss -s → 重传 → 带宽
└─ 负载高但四项都正常?─→ D 状态堆积:ps stat 数 D → 往下挖存储/NFS
配套巡检(事后长期观测):sar(sysstat)每天留档,回溯"昨天 3 点发生了什么"------这也正是阶段四要接 Prometheus 的理由:人肉 sar 只能看到"已发生",监控能看到"正在逼近"。
验收标准:拿任意一台机器,按决策树 5 分钟内说出瓶颈方向与肇事进程;能解释 available 与 free、负载与 CPU 使用率的区别。
七、🚨 避坑清单
| # | 坑 | 误判 | 正确姿势 |
|---|---|---|---|
| 1 | free 少了就报警 | 缓存机制被无视 | 只看 available |
| 2 | 负载高=CPU 不足 | 扩容 CPU(实际是磁盘慢) | 负载含 D 状态,先看 wa |
| 3 | 只看 top 瞬时值 | 排查被抖动误导 | pidstat/vmstat 带"间隔采样" |
| 4 | iostat 只看 %util | SSD 并发误判 | await 才是体感指标 |
| 5 | TIME_WAIT 当故障 | 乱改内核参数 | TIME_WAIT 是正常机制,先确认业务受损 |
| 6 | 忘查 dmesg | OOM、磁盘错误漏诊 | 三板斧之一固定带上 |
| 7 | 云机器不看 st 值 | 宿主机超卖误当自己锅 | st>0 考虑迁移实例/提工单 |
| 8 | 一次排查只跑一遍 | 撞上偶发问题 | sar 留档 + 监控告警接管 |
八、一句话总结
三板斧(uptime/top/dmesg)定方向,四条线各走三步,方向舵是 us/sy/wa 与 available------性能排查不是玄学,是一棵可以背下来的决策树。
💬 互动
你排查过最曲折的性能问题是什么?最后发现是"磁盘慢伪装成 CPU 高"还是"邻居超卖"?评论区还原现场。
下一篇预告:《S2-06 Linux 启动流程与故障修复:GRUB、systemd 与救援模式》------系统进阶收官:改错 fstab 开不了机怎么办、root 密码忘了怎么救。