先看几个例子

第一台机器
关键指标拆解
- 负载 load average:1.23
负载很低,系统整体压力小。 - Tasks:1 running,135 sleeping
同样现象:同一时刻只有1个线程在运行,其余全部休眠阻塞。 - CPU指标
us 1.8:业务用户CPU很低;ni 14.8:nice(低优先级进程)占用,这个是比较显眼的点;id 78.1:CPU大量空闲;wa 2.0:有轻微IO等待(2%,不算严重);st 0.1:几乎没有被宿主机偷时间。
- ⚠️内存状态需要留意
- 总内存约 16G;
- 物理空闲
free=371.9MiB,剩余物理内存很少; avail Mem 2973.8 MiB:系统可用内存约2.9G(包含cache回收);- Swap已经使用2215MB,说明有部分内存被置换到交换分区。>
free很小不代表OOM,要看
avail Mem,但swap上升代表内存压力开始显现,需要关注,持续上涨就会性能抖动。
这台机器需要关注两点
-
内存压力:free已经很低,swap在使用,观察是否持续走高。
#观察swap变化
vmstat 1 -
同样执行
jstack <java-pid>导出线程快照,查看大量线程阻塞在哪里。 -
可以用
iotop确认那2%wa是哪个进程产生的IO。
简单理解各个字段记忆
free:完全空闲物理内存;avail Mem:真正给新程序可用的内存(内核可以回收buff/cache),这个值才是判断内存是否危险的核心;- swap used持续上涨:说明应用实际内存需求大于物理内存,会变慢。
这台机器CPU资源很富余,瓶颈不在CPU;但内存需要盯一下。
第二台机器

关键指标拆解
- 负载 load average=2.95
机器16G内存,load接近3,不算很高。
再次看到经典现象:
1 running,138 sleeping,全局只有1个线程处于运行状态,绝大多数线程休眠阻塞,和另外两台业务机器一模一样。
- CPU分布
us 32.1:业务用户态占用;sy 21.2:系统内核CPU占比偏高;id 31.1:CPU还有31%空闲,CPU资源没有打满;wa 4.7:存在一定磁盘IO等待;- si 10.4 很高 :
si软中断,网络小包多(大量TCP收发、短连接、MQ、数据库网络交互,会拉高si)。
- 内存(这台状态健康)
- 物理内存16G;
avail Mem 9107.8 MiB≈9G可用内存,非常充足;- Swap只用182MB,几乎没用到swap,没有内存压力。
两台机器横向对比汇总
| 机器 | load | running线程 | 内存情况 | 特征 |
|---|---|---|---|---|
| 10.101.2.145 | 1.23 | 1 | 紧张,swap上涨 | CPU空闲,内存压力,少量wa |
| 10.101.2.36 | 2.95 | 1 | 充足 | 内核sy高、软中断si高,有iowait |
两台机器共同的核心特征:running线程数量极少,大量线程sleep 。
说明业务应用内部大量线程阻塞等待(数据库连接、锁、消息队列、外部调用),就绪可交给CPU执行的线程很少,导致多核CPU不能充分跑满。
针对这台机器的关注点
si=10.4软中断偏高:说明网络流量压力不小,检查:MQ、数据库交互、接口请求量。wa=4.7:有磁盘IO等待,执行iotop -oP看是谁在做磁盘读写。- 依旧需要导出jstack快照,定位大量sleep线程到底阻塞在哪一行代码。
sy内核态CPU 21.2%偏高,结合高si,大概率大量socket系统调用。
排查命令
#看磁盘IO进程
iotop -oP
#看网络连接统计
ss -s
#导出java线程栈
jstack <pid> > jstack‑36.log
不是操作系统、docker限制多核;是Java应用层,业务线程拿不到资源,卡在等待状态,CPU有空闲资源却没有任务可以调度上去。
总结
top可以对线程、CPU、IO、内存、交换内存进行监控。特别容易忽略的是wa,这个指标都不会太重视,如果对于大数据的处理,是需要掌握磁盘IO的效率的。
小技巧:在top界面上按1,可以列出每个cpu的使用效率。
