CPU 飙高 ≠ 服务器真的卡?
在 Linux 服务器运维中,相信很多人都遇到过这种情况:监控平台报警"CPU 使用率 95%+",登录服务器查看却发现服务响应正常,业务无感知;反之,偶尔 CPU 使用率仅 60%,业务却出现延迟、请求超时。
很多人默认"CPU 飙高 = 服务器卡顿",但实际上,CPU 使用率只是表象,真正决定服务器是否"卡顿"的是进程状态、IO 等待、资源竞争等核心指标。本文结合 Ansible 自动化批量排查案例、生产环境真实故障场景,从原理到实操,完整拆解 Linux 服务器 CPU 相关的卡顿排查全流程。
Linux 服务器卡顿故障排查实战指南
CPU 高 ≠ 卡顿
很多运维同学的排查第一步是 top,看到 CPU 低就放松警惕,看到 CPU 高就盲目杀进程。这是危险的习惯。
| 维度 | 含义 | 核心影响 |
|---|---|---|
| us(用户空间) | 用户进程(业务程序、中间件)占用 CPU 时间 | 业务代码问题、高并发请求、内存泄漏导致的 CPU 空转 |
| sy(系统空间) | 内核态(进程调度、IO 调用、网络处理)占用 CPU 时间 | 系统调用频繁、进程切换过多、内核参数配置不当 |
| wa(IO 等待) | 进程等待 IO 完成(磁盘、网络、数据库)的 CPU 空闲时间 | 这是"假卡顿"的核心诱因!CPU 没干活,但进程在等 IO,看似 CPU 低,实则业务阻塞 |
| hi/si(硬中断/软中断) | 处理硬件中断(网卡、磁盘)、软中断(网络包、定时器)的时间 | 网络风暴、磁盘 IO 异常、中断队列积压 |
| 场景 | CPU 表现 | 实际体验 | 原因 |
|---|---|---|---|
| 视频转码服务 | 90%+ | 流畅 | 充分利用多核,IO 不阻塞 |
| 内存密集型应用 | 20% | 极度卡顿 | 频繁换页,CPU 等待内存 |
| 磁盘 IO 阻塞 | 10% | 命令无响应 | 进程处于 D 状态,不可中断睡眠 |
| 网络延迟 | 30% | 接口超时 | CPU 空闲等待网络 ACK |
结论 :卡顿是体感指标 ,CPU 是资源指标。两者有关联,但绝非等价。
卡顿的原因是谁在等待?
Linux 下进程常见的状态决定了"卡"的根源:
bash
# 查看进程状态
ps aux | awk '{print $8}' | sort | uniq -c | sort -rn
| 状态码 | 含义 | 卡顿关联 |
|---|---|---|
| R | 运行/就绪 | 正常,可能在抢 CPU |
| S | 可中断睡眠 | 通常正常,等待事件 |
| D | 不可中断睡眠 | 🔴 高危!通常是 IO 阻塞 |
| Z | 僵尸进程 | 资源泄漏,需处理 |
| T | 停止状态 | 被信号暂停 |
大量 D 状态进程 = 系统级卡顿,CPU 再低也没用。
排查方法
确认"卡"的定义
先问三个问题:
- 谁卡? 单个应用 vs 整个系统 vs SSH 都连不上
- 什么操作卡? 特定接口 vs 所有操作 vs 仅写操作
- 何时开始? 突发 vs 渐进 vs 定时出现
💡 注意 :如果 SSH 登录都困难,优先检查内存和磁盘 IO,而非 CPU。
全局资源视图(别只看 CPU)
bash
# 1. 综合资源监控(比 top 更全面)
vmstat -w 1 10
# 关键列解读:
# r: 运行队列长度(持续>CPU核数=CPU瓶颈)
# b: 阻塞队列(>0 且持续=IO/内存瓶颈)
# si/so: 换入换出(>0=内存不足,正在swap)
# us/sy/id/wa: 用户态/内核态/空闲/IO等待(wa高=IO瓶颈)
输出示例分析:
text
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 8 0 23456 12345 567890 0 0 0 0 10 20 5 3 0 92 0
🔴 危险信号 :
b=8(大量阻塞),wa=92(CPU 几乎全在等待 IO),这就是"CPU 10% 但系统卡死"的典型场景。
IO 深度诊断
bash
# 2. 磁盘 IO 实时监控(比 iostat 更直观)
iostat -xz 1
# 关键指标:
# %util: 接近 100% 表示磁盘饱和
# await: 平均等待时间(>20ms 需警惕,>50ms 严重)
# svctm: 服务时间(应接近物理极限,SSD<1ms,HDD<10ms)
比如这个情况:数据库备份导致业务卡顿
bash
# 发现 nvme0n1 的 %util=99%,await=300ms
# 但 CPU 只有 15%
# 根因:备份进程占满磁盘带宽,业务 IO 排队
进阶工具:
bash
# 查看具体进程的 IO 情况
iotop -oP
# 查看 IO 延迟直方图(需 bcc 工具)
biolatency-bpfcc
内存与 Swap 陷阱
bash
# 3. 内存深度分析
free -h && cat /proc/meminfo | grep -E "(Dirty|Writeback|AnonPages)"
# 关键观察点:
# - Dirty 数据大:大量数据待写盘,可能引发 IO 风暴
# - Writeback 高:正在回写,磁盘压力大
# - AnonPages 突增:应用内存泄漏或突发负载
隐形杀手:Swap 抖动
bash
# 查看哪些进程在 swap
for pid in $(ls /proc | grep -E "^[0-9]+$"); do
if [ -f /proc/$pid/smaps ]; then
swap=$(awk '/Swap:/ {sum+=$2} END {print sum}' /proc/$pid/smaps 2>/dev/null)
if [ "$swap" -gt 0 ]; then
cmd=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ')
echo "PID: $pid, Swap: ${swap}KB, CMD: $cmd"
fi
fi
done | sort -k3 -rn | head -10
网络与系统调用
bash
# 4. 网络连接状态(连接数过多导致"假死")
ss -s
ss -tan state time-wait | wc -l # TIME_WAIT 过多?
ss -tan state close-wait | wc -l # CLOSE_WAIT 泄漏?
# 5. 系统调用追踪(定位具体卡点)
strace -cp <pid> # 统计耗时系统调用
strace -tt -T -p <pid> 2>&1 | head -100 # 查看具体延迟
生产环境排查实战
快速区分真假卡顿
排查的核心原则:先看整体指标,再抓具体进程,最后定位根因。
核心命令组合:10 秒判断卡顿类型
执行以下命令组合,快速获取关键指标,判断卡顿类型:
bash
# 1. 查看 CPU 使用率、进程状态、负载(核心指标)
top -c -n 1 -b | head -20
# 2. 查看系统负载(判断是否真过载)
uptime
# 3. 查看进程状态(区分 Running 与 Waiting)
ps -eo pid,cmd,%cpu,%mem,state --sort=-%cpu | head -10
# 4. 查看 IO 等待(关键:判断是否为 IO 导致的假卡顿)
iostat -x 1 3
指标解读
- load average :取 1 分钟平均值,若超过 CPU 核心数 × 2,大概率为真卡顿;
- %wa :若 wa > 20%,优先排查 IO 问题,而非 CPU;
- 进程 state :
R(Running)为正在占用 CPU,D(不可中断睡眠)为等待 IO,S(可中断睡眠)为正常等待; - CPU 使用率分布:us/sy 占比>90% 且 wa <5% → 计算密集型真卡顿;us/sy 占比<50% 且 wa >30% → IO 等待型假卡顿。
实战案例:识别假卡顿
生产场景 :监控报警业务服务器 CPU 使用率 92%,登录后执行 top 发现:
- us 90%、sy 2%、wa 1%;
- load average 1.5(CPU 核心数 4);
- 前 3 个进程为业务日志压缩进程,state 均为
R,无请求队列积压; - 业务接口响应时间<100ms,正常无延迟。
结论 :此为计算密集型假卡顿,CPU 被日志压缩进程占用,但业务无影响,无需处理,仅需调整日志压缩策略即可。
CPU 飙高的 4 大核心场景与解决方案
若判断为真卡顿,按"进程 → 系统 → 代码"的顺序逐层排查,以下为生产环境最高频的 4 大场景,附实操命令与最佳实践。
业务进程 CPU 飙高
排查步骤
-
定位占 CPU 最高的进程 PID:
bash# 按 CPU 使用率排序,取前 5 个进程 ps -p $(ps -eo pid --sort=-%cpu | head -n 6 | tail -n 5) -o pid,cmd,%cpu,%mem -
定位进程内的高 CPU 线程:
bash# 替换 PID 为目标进程 ID,查看线程 CPU 占用 top -H -p PID -
分析线程堆栈(定位代码问题):
bash# 打印线程堆栈,保存到文件便于分析 pstack PID > pid-stack.log # 或使用 perf 深度分析(生产环境谨慎使用,避免影响性能) perf trace -p PID -g > perf-trace.log
系统态 CPU 飙高(内核/调度问题)
排查步骤
-
查看系统态 CPU 占比:
bashmpstat 1 5 -
查看进程切换次数(上下文切换):
bash# 查看自愿/非自愿切换次数 vmstat 1 5 # 关键指标:cs(上下文切换次数),若>100万/秒,需排查 -
查看内核中断情况:
bashcat /proc/interrupts
常见原因与解决方案
| 原因 | 典型现象 | 解决方案 |
|---|---|---|
| 进程切换过多 | sy >30%,cs >100万/秒 | 减少进程数、合并小进程、调整内核调度参数(如 sched_mc) |
| 网络中断风暴 | si >20%,网卡流量异常 | 排查 DDoS 攻击、优化网卡队列、开启网卡多队列(RSS) |
| 磁盘中断异常 | 磁盘 IO 正常,sy 飙高 | 修复磁盘驱动、升级内核版本、调整 IO 调度算法(如 noop) |
软中断 CPU 飙高(网络/磁盘问题)
排查步骤
-
查看软中断 CPU 占比:
bashwatch -n 1 cat /proc/softirqs -
定位高软中断类型:
- 若
NET_RX(网络接收)占比高 → 网络包风暴; - 若
BLOCK(磁盘)占比高 → 磁盘 IO 异常;
- 若
-
排查网络/磁盘:
bash# 网络流量排查 iftop -i eth0 # 磁盘 IO 排查 iotop -o
解决方案
- 网络风暴:封禁异常 IP、接入 WAF、优化防火墙规则;
- 磁盘异常:修复磁盘坏道、更换故障磁盘、清理无效文件、优化 IO 并发。
虚拟化层 CPU 限制(云服务器专属)
若为云服务器(如阿里云、腾讯云),可能是虚拟化层 CPU 限制导致的"假飙高":
-
查看 CPU 抢占情况:
bashcat /proc/schedstat -
查看云厂商监控(如阿里云云监控):
- 若出现 CPU 抢占时间(steal)>5% → 虚拟化层资源竞争,需提交工单扩容或更换宿主机。
构建你的卡顿排查 SOP
bash
#!/bin/bash
# 快速卡顿排查脚本 - quick_check.sh
echo "=== 1. 系统负载与 CPU ==="
uptime
mpstat -P ALL 1 1 | tail -n 5
echo -e "\n=== 2. 内存与 Swap ==="
free -h
vmstat -s | grep -E "(swap|paged|pageout)"
echo -e "\n=== 3. IO 状态 ==="
iostat -xz 1 1 | tail -n 10
echo -e "\n=== 4. D 状态进程(卡顿元凶)==="
ps aux | awk '$8 ~ /^D/ {print $0}' | head -5
echo -e "\n=== 5. 网络连接 ==="
ss -s | head -10
echo -e "\n=== 6. 最近 OOM 或硬件错误 ==="
dmesg | grep -iE "(error|fail|oom|blocked)" | tail -5
总结:卡顿排查的思维模型
单个应用慢
整个系统无响应
是
否
❌ 无法登录
✅ 可以登录
CPU 高
内存不足
IO 瓶颈
网络问题
配置问题
代码问题
资源不足
外部攻击
🚨 用户反馈系统卡顿
卡顿范围判断
局部卡顿
全局卡顿
检查应用日志
应用本身问题?
修复应用配置/代码
SSH 能登录?
网络/内存严重问题
使用带外管理: IPMI/iLO/iDRAC
强制重启/现场排查
执行快速排查脚本
vmstat 1 5 - 查看 CPU/内存/IO
iostat -x 1 5 - 查看磁盘 IO
ss -s - 查看网络连接
dmesg | tail - 查看内核错误
定位资源瓶颈
top/htop 找高 CPU 进程
free -h / ps aux 找内存大户
iotop 找高 IO 进程
ss -tan 查看连接状态
使用 strace/pstack 分析进程
根因定位
调整系统/应用参数
修复代码/升级版本
扩容 CPU/内存/磁盘
封禁 IP/加固安全
✅ 问题修复
持续监控验证
记录复盘文档
最后的话 :优秀的运维不是"看到告警就处理",而是建立系统性的观测能力。当你能解释"为什么 CPU 20% 但系统卡死"时,你就真正理解了 Linux 的资源调度机制。
本文基于 Linux 内核 4.x/5.x 行为编写,工具以 CentOS/Ubuntu 通用版本为例。建议收藏并在测试环境验证命令后再用于生产。