做服务器运维的兄弟应该都听过一句经典的求救消息:服务器卡了,帮我看看。“卡”这个字背后其实藏着完全不同的处境——CPU忙到转不过来、内存耗尽开始疯狂换页、带宽跑满导致业务请求堵在门口,甚至三者同时发生,你连命令行都敲不利索。如果只拿 top 瞄一眼就下结论,十次有八次会跑偏。这篇内容把 Linux 服务器性能排查里最常用的 CPU、内存、带宽指标从查询命令到分析逻辑串成一条线,帮你看清一个故障背后到底是哪类资源不够,以及如何用一套命令快速定位高亮进程和流量来源。刚接手服务器的新人可以直接照做,偶尔需要救急的开发也能当速查手册用。
1. 先别急着下结论:CPU、内存、带宽的排查顺序是门技术活
很多人拿到“服务器慢”的信号,第一反应就是冲到机器面前敲 top。top 确实能看全局,但光看一屏数字没用,你得先判断这个“慢”属于哪一类:是 CPU 耗尽导致请求排队,是内存不足导致频繁 swap,还是网络吞吐不够导致用户侧一直打转。判断错了,后面花再多时间都白搭。
1.1 不同故障表象背后,对应的指标完全不同
我习惯先把问题现象拆成三类,再决定走哪条排查路径。
| 用户/业务表现 | 最可能的瓶颈 | 第一眼要看的数据 | 核心命令 |
|---|---|---|---|
| CPU 长时间高位,接口响应慢 | CPU 算力不够或进程死循环 | load average、us/sy/wa、进程 CPU% | top、mpstat、pidstat |
| 频繁卡顿,但界面看 CPU 并不高 | 内存不足/swap、磁盘等待 | available、si/so、iowait、D 状态进程 | free、vmstat、pidstat -d |
| 页面加载极慢、视频转圈、下载速度低 | 带宽不足、网络延迟、TCP 队列堆积 | 网卡 rx/tx、连接状态、丢包率 | sar -n DEV、iftop、mtr、ss |
| 服务偶发超时,CPU 内存都正常 | 连接数/端口/文件句柄不足 | TIME_WAIT、ESTABLISHED、句柄数 | ss -s、ss -tan、ulimit |
这张表不绝对,但能给个大概方向。比如用户反馈“网站能打开,就是慢得像幻灯片”,你如果一直盯着 CPU 和内存看,可能什么都看不出来,实际上只要用 sar -n DEV 看一眼网卡流量,就能发现出口带宽已经打满。反过来,如果业务进程报“无法分配内存”,但 free 显示 buff/cache 很高,你的精力应该放在应用层是不是一次性申请了太多内存,而不是简单加物理内存条。
1.2 动手之前,先把“事故现场”完整留下来
真实故障里最忌讳的一件事,就是还没弄清原因就把服务重启了。重启能解决一时的问题,但会把你唯一的现场证物毁掉。尤其是 Linux 性能排查,很多线索藏在 /proc、/sys、syslog、内核 dmesg 里,服务一停这些数据可能就断了。
我到一台出问题的机器上,第一件事通常是建一个日志目录,把当前能采集的性能快照一次性落盘,再做后续操作。下面这段脚本可以手动跑,也可以写成一个 base64 命令直接远程下发:
bash复制mkdir -p /var/log/perfcheck
dt=$(date +%F_%H%M%S)
{
echo "---------- uptime ----------"
uptime
echo "---------- top head ----------"
top -b -n1 | head -25
echo "---------- free ----------"
free -h
echo "---------- vmstat 1 5 ----------"
vmstat 1 5
echo "---------- mpstat ----------"
mpstat -P ALL 1 3 2>/dev/null || true
echo "---------- sar net ----------"
sar -n DEV 1 3 2>/dev/null || true
echo "---------- network sockets ----------"
ss -s
echo "---------- dmesg tail ----------"
dmesg -T | tail -30
} > /var/log/perfcheck/$dt.log 2>&1
这段采集不需要额外装什么包,在大多数能正常跑 Linux 的机器上直接就能看。top、free、vmstat、ss 属于 procps 或 iproute2 系列,mpstat 和 sar 属于 sysstat,某些精简镜像可能没有后两个,脚本里加了 2>/dev/null || true 避免直接中断。先落盘而不是只打印到屏幕,是因为高负载时 ssh 都可能间歇卡住,你来不及往下翻,日志文件在本地存着随时可以看。这也是我踩过坑之后的习惯:有些服务器负载一高,终端输出一行要等好几秒,但写文件却基本不受影响。
最近有不少读者在问一个很实际的问题:在一台 Ubuntu 宿主机上,用一个升级包把 Rocky Linux 环境跑起来,像是 bcoreos 实战里那种用法,出了性能问题应该怎么排查。其实这类交叉发行版环境本质上还是共享同一个 Linux 内核,CPU、内存、带宽的统计都发生在宿主机侧,下文讲的命令和判断思路完全适用。下面的内容就按这个链路逐层展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CPU 性能排查:从 load average 到热点函数,逐层下钻
CPU 排查是所有性能问题里最直观的一类,因为工具成熟、指标明确。但陷阱也不少,最经典的坑就是:load average 高不等于 CPU 满,CPU 使用率高不等于用户态程序忙,单核 100% 不等于整机 100%。
2.1 load average 高,不代表 CPU 已经满载
load average 是 Linux 性能排查里最常被误读的指标。很多人看到 load average 为 8,第一反应是“CPU 不够了,要加核”。这个结论在 8 核机器上可能成立,但在 4 核机器上又必须结合上下文判断,更麻烦的是 load 不只统计正在运行的进程,还统计处于不可中断睡眠状态的进程。
系统负载的计算对象包括两类:一是 TASK_RUNNING,也就是正在跑或排队等 CPU 的线程;二是不可中断睡眠状态,典型的如等待磁盘 I/O。所以你能看到一台 CPU 占用很低、但 load 非常高的机器,多半是 iowait 高导致的,比如磁盘阵列卡故障、文件系统卡住、NFS 挂载点不可用。
判断方法是先看 uptime,再用 vmstat 1 3 看第二、第三列的 r 和 b:
bash复制uptime
vmstat 1 5
vmstat 输出里 r 列是运行队列长度,b 列是阻塞在不可中断状态(通常等 I/O)的进程数。如果 r 远大于 CPU 核数,说明 CPU 队列严重排队;如果 b 很大、r 不大,同时 top 显示 %wa 高,瓶颈多半在磁盘而不是 CPU。这个时候你加多少个 vCPU 都没用,得先从磁盘 I/O 和服务进程入手。
cat /proc/loadavg 是最底层的负载来源,和 uptime 显示的负载一致。想要看历史趋势,用 sysstat 的 sar -q 更合适,它能按时间回溯更早的 load 情况,很适合做“昨天和今天的故障对比”。
2.2 用 top、mpstat、pidstat 按层级定位高 CPU 进程
如果确认是 CPU 忙,下一步要按“整机 → 单核 → 进程 → 线程”的层级下钻。整机层面我用 top 或 mpstat -P ALL 1 3,进程层面用 top -bn1 -o %CPU 或 ps,线程和调用栈层面再用更细的工具。
先看整机使用率:
bash复制top -b -n1 | head -15
mpstat -P ALL 1 3
top 最上面一行的 %Cpu(s) 会显示 us、sy、ni、wa、hi、si、st、id 几类。我重点看 us(用户态时间)和 sy(内核态时间)。如果 sy 长期超过 30%,就要怀疑系统调用、中断处理或内核问题,不完全是业务代码在消耗。
top 默认显示的是所有 CPU 的平均值,这不代表每个核都一样。想观察单核负载,按 1 展开每个逻辑核,或者直接用 mpstat:
bash复制mpstat -P ALL 1 3
输出会按 CPU0、CPU1 逐个列出。我曾经遇到过一个压测环境,业务只用了 1 个 worker 进程,整体 CPU 使用率看起来只有 25%,实际上 CPU0 已经被打满,导致请求排在一个核上。如果只看平均值,会误判成“负载不高”。这就是为什么我建议在生产机器上先把 mpstat 跑一遍的原因,尤其是有绑核、cpu 智能核心调度、NUMA 结构的机器,单核热点是常见问题。
要精确定位进程,用 pidstat 比 raw top 更方便落脚本:
bash复制pidstat -u 1 5
pidstat 输出里 %CPU 是采样周期内的真实占用,比 ps 的 %cpu 字段更准确。ps 的 %cpu 是进程生命周期内的累计平均,很多瞬间飙高的进程在 ps 里看不到,但在 pidstat 里一下就能暴露出来。我通常习惯两个命令搭配使用:
bash复制ps -eo pid,user,stat,%cpu,%mem,cmd --sort=-%cpu | head -15
pidstat -u 1 5 | sort -k7 -rn | head -15
第一行瞬间抓大,第二行持续观察变化。
