CPU使用率是否真高需分三类看:%us、%sy、%wa;%wa>20%说明I/O瓶颈而非CPU,结合pidstat、mpstat和top Shift+I模式综合判断。

怎么看 CPU 使用率是否真的高?
Linux 的 top 或 htop 显示的 %CPU 常被误读。关键要看三类值:用户态(%us)、内核态(%sy)、等待 I/O(%wa)——如果 %wa 长期 >20%,说明不是 CPU 瓶颈,而是磁盘或网络卡住了。
更准的做法是结合 pidstat -u 1 查单个进程的真正 CPU 消耗,避免被短时峰值误导。注意:top 默认按 CPU% 排序,但会把多核总和当 100%,比如 4 核机器满载显示为 400%,需用 top → Shift+I 切换到“整体使用率”模式(即归一化到 100%)。
-
mpstat -P ALL 1可查看每颗 CPU 核心的负载差异,排查不均衡调度 - Java 进程常因 GC 导致
%sy升高,此时要查jstat -gc而非只盯%us - 容器环境里,
docker stats显示的 CPU% 是相对于容器限制值(--cpus)计算的,不是宿主机物理核占比
内存到底够不够?别只看 free -h 的 available
available 字段是内核估算的“当前可立即分配的内存”,比 free 更靠谱,但它不包含可快速回收的 page cache。真实压力要看 pgpgin/pgpgout 和 pgmajfault:
watch -n 1 'grep -E "pgpgin|pgpgout|pgmajfault" /proc/vmstat'
若 pgmajfault 每秒持续 >100,说明频繁缺页中断,进程在反复申请新内存又释放;若 pgpgin 远大于 pgpgout,可能有内存泄漏或缓存堆积。
- 应用堆内存(如 Java
-Xmx)设得过大,反而会推高pgmajfault,因为内核要花更多时间找连续物理页 -
slabtop能定位内核模块(如xfs_inode、ext4_inode_cache)是否占用了异常多的 slab 内存 -
/proc/meminfo中的MemAvailable是动态估算值,低内存设备上可能滞后,建议同时看Committed_AS / CommitLimit比值是否 >90%
磁盘 I/O 等待时间(%util)为什么不准?
iostat -x 1 输出的 %util 只表示设备忙的时间百分比,不反映队列深度或响应延迟。SSD 或 NVMe 设备即使 %util 为 100%,await 也可能只有 0.1ms;而机械盘 %util 70% 时 await 已达 20ms+,才是真正瓶颈。
更关键的指标是 avgqu-sz(平均队列长度)和 r_await/w_await(读写平均延迟)。当 avgqu-sz > 1 且 r_await > 10(HDD)或 > 1(NVMe),说明 I/O 请求开始排队。
- 使用
iotop -oPa可直接看到哪些进程在发起同步 I/O(IO列非 0),比ps aux --sort=-%cpu更准 - LVM 或加密设备(如 LUKS)会在
dm-*层引入额外延迟,iostat要加-d参数才能显示底层物理设备(如sda)的真实指标 -
cat /sys/block/sda/queue/scheduler查当前 IO 调度器,云主机常用none(绕过内核调度),本地 HDD 应设为deadline
网络丢包和重传怎么快速定位?
netstat -s 或 ss -s 显示的 “retransmits” 是累计值,看不出实时恶化趋势。应优先看:
watch -n 1 'ss -i | grep -E "(retrans|rtt)" | head -5'
重点关注每行末尾的 retrans 计数(单连接重传次数)和 rtt(往返时间)。若某连接 retrans:2+ 且 rtt:1000+(ms),基本可判定链路不稳定。
-
tcpretrans(bpftrace 工具)能追踪每个重传报文的原始 socket 和进程,比tcpdump更轻量 - 云环境常见问题是网卡多队列未绑定 IRQ,导致单核软中断(
softirq)打满,用cat /proc/interrupts | grep eth0查各 CPU 上网卡中断分布 -
ethtool -S eth0中的rx_missed_errors或tx_aborted_errors非零,说明驱动或硬件层已出问题,不是 TCP 协议栈能解决的
这些指标之间很少孤立变化。比如 %wa 升高时,大概率伴随 pgpgin 暴涨和 r_await 上升——与其单独调优某一项,不如用 perf record -e syscalls:sys_enter_read,syscalls:sys_enter_write -a sleep 10 抓系统调用热点,从源头看进程到底在等什么。










