这种情况在云服务器(尤其是腾讯云的 CVM)中非常典型:“系统负载低”但“用户感知卡顿”,通常意味着瓶颈不在 CPU 计算能力上,而可能在于I/O 等待、网络延迟、内存交换或外部依赖。
以下是针对该场景的系统化排查思路和操作步骤:
1. 核心矛盾分析:为什么负载低却卡顿?
Linux 的 load average(负载)主要反映的是运行队列中的进程数(包括正在运行和等待 CPU 的进程)。
- 高负载卡顿:CPU 跑满了,所有进程都在排队等 CPU。
- 低负载卡顿:进程在等待 I/O(磁盘读写、网络包处理),此时进程处于
D状态(不可中断睡眠),它们不占用 CPU,所以负载显示不高,但程序会卡住不动。
2. 第一步:检查磁盘 I/O(最常见原因)
如果应用频繁读写磁盘,或者云盘性能达到上限,进程会卡在 D 状态,导致页面响应极慢,但 CPU 使用率可能只有几%。
- 排查命令:
# 实时查看磁盘 IO 情况,重点关注 iowait iostat -x 1 # 或者使用更详细的 vmstat 查看上下文切换和阻塞 vmstat 1 5 - 关键指标:
iowait:如果长期高于 10%-20%,说明磁盘是瓶颈。%util(Device Utilization):如果接近 100%,说明磁盘带宽已饱和。await:平均每次 I/O 操作的等待时间,如果数值很大(如超过 100ms),说明磁盘响应慢。
- 腾讯云特有排查:
- 登录 腾讯云控制台 -> 云监控 -> 查看该实例的 云硬盘监控。
- 检查 读写吞吐量 和 IOPS 是否达到了所购云盘规格的上限(例如普通云盘有突发性能限制,高性能云盘也有上限)。
- 如果是按量付费且使用了本地盘,注意其性能波动较大;如果是云盘,检查是否触发了性能模式限制(如标准云盘在低配时会有 IOPS 限制)。
3. 第二步:检查内存与 Swap 交换
如果物理内存不足,系统会将数据换出到 Swap(虚拟内存)分区。Swap 的速度比内存慢几个数量级,会导致严重的卡顿,但 CPU 并不忙。
- 排查命令:
free -h # 查看是否有频繁的 swap in/out vmstat 1 5 | grep si/so - 判断依据:
- 如果
si(swap in) 或so(swap out) 有持续的数据传输,说明发生了内存抖动(Thrashing)。 - 即使
free内存看起来还有剩余,也可能是因为 Linux 将空闲内存用于了 Page Cache,导致应用可用内存不足。
- 如果
- 解决方案:增加内存、优化应用内存配置、或清理缓存(慎用,可能导致瞬时卡顿)。
4. 第三步:检查网络延迟与丢包
有时卡顿是因为网络包发送不出去或接收不到,导致应用线程阻塞在网络 I/O 上。
- 排查命令:
# 查看网络接口统计,关注 drop 和 err netstat -i # 抓包分析(需要 root) tcpdump -i eth0 -c 100 - 腾讯云特有排查:
- 登录 云监控,查看 公网流量 和 内网流量 图表。
- 检查是否有安全组规则限制了端口,导致连接被丢弃。
- 检查带宽峰值:如果业务突发流量打满带宽,会导致后续请求排队,产生高延迟。
- 跨区/跨可用区访问:如果数据库或缓存位于其他可用区,网络延迟会显著增加。
5. 第四步:深入查看“僵尸”进程状态
通过 top 或 ps 命令直接观察进程状态,确认是否有大量进程处于 D 状态。
- 操作:
top # 在 top 界面按 'w' 进入编辑模式,添加 'S' 列(状态列) # 或者直接看第一行 Load Average 下方的 CPU 行 - 现象:
- 如果看到大量的
D(Uninterruptible sleep) 状态的进程,基本可以确认为 I/O 阻塞(通常是磁盘或 NFS 挂载点问题)。 - 如果看到
R(Running) 很高但 Load 不高,可能是 CPU 调度问题(较少见)。
- 如果看到大量的
6. 第五步:应用层与中间件排查
如果底层资源(CPU/IO/Mem/Net)都正常,问题可能出在应用逻辑本身。
- 常见原因:
- 锁竞争:多线程应用中,某个线程持有了锁,其他线程在等待,导致整体响应变慢。
- 数据库慢查询:应用线程在等待数据库返回结果,此时应用服务器 CPU 很低,但数据库端负载可能很高。
- GC(垃圾回收):Java 等语言应用在进行 Full GC 时,会出现"Stop-The-World"现象,导致服务暂停,但 CPU 监控可能显示不高。
- 排查建议:
- 查看应用日志(如 Nginx access.log, Tomcat/Java logs),寻找
timeout或slow query记录。 - 使用 APM 工具(如腾讯云可观测性平台 TKE/Apollo 集成,或 SkyWalking)追踪调用链,定位耗时最长的节点。
- 查看应用日志(如 Nginx access.log, Tomcat/Java logs),寻找
7. 第六步:云平台层面的干扰(特殊场景)
- 宿主机噪音邻居(Noisy Neighbor):虽然概率较低,但如果同一台物理宿主机上的其他虚拟机异常占用了资源,可能会影响你的实例。
- 验证方法:在卡顿发生时,尝试重启实例(如果允许),观察是否恢复正常。如果恢复后过一段时间又出现,可能是宿主机硬件故障或资源争抢。
- 弹性伸缩策略:如果是自动伸缩组,是否在扩容前瞬间资源耗尽?
总结与建议行动清单
| 排查方向 | 关键指标/命令 | 疑似症状 | 推荐动作 |
|---|---|---|---|
| 磁盘 I/O | iostat -x 1, %util, await |
iowait 高,进程状态为 D |
升级云盘类型(如从普通云盘升至 ESSD),优化代码减少同步写,检查磁盘健康度。 |
| 内存/Swap | free -h, vmstat |
si/so 有数据,内存频繁交换 |
增加内存,优化应用内存配置,关闭不必要的 Swap。 |
| 网络 | netstat -i, 云监控带宽图 |
丢包率高,带宽打满 | 检查安全组,购买更高带宽,优化 CDN 提速。 |
| 应用/DB | 应用日志,慢查询日志 | 数据库连接超时,Full GC | 优化 SQL,调整 JVM 参数,增加 DB 实例规格。 |
| 云监控 | 腾讯云控制台图表 | 资源曲线平稳但业务报错 | 结合上述步骤,重点看云盘 IOPS/吞吐量是否触顶。 |
快速诊断建议:
下次遇到卡顿,立即登录服务器执行以下组合命令,截图保存,这通常能直接定位问题:
# 1. 看整体负载和 IO 等待
uptime && iostat -x 1 3
# 2. 看内存和 Swap
free -h && vmstat 1 3
# 3. 看是否有 D 状态进程
ps aux --sort=-%cpu | head -n 20
# 4. 查看最近系统日志中的错误
dmesg -T | tail -n 50
如果以上步骤均无法解决,建议直接提交工单给腾讯云技术支持,要求他们协助查看宿主机层面的底层日志,这往往能发现用户层面无法获取的信息。
CLOUD技术笔记