在云服务器上执行top命令时,最右侧的%st字段往往被忽略,但它却是判断虚拟化CPU是否被争抢的关键。steal time表示vCPU处于就绪状态后,宿主机物理CPU却一直在运行其他实例,导致本实例vCPU等待调度的累计时间占CPU总时间的百分比。这个值不是自身进程消耗的CPU,而是被虚拟化层偷走的时间。

许多云主机用户会在发现接口响应变慢、毛刺增多后查看监控,却只看到自己业务进程的CPU使用率不高,于是误以为系统没有问题。实际上,只要宿主机上的物理核被其他实例占满,即使本实例的vCPU上有任务要执行,也必须排队等待。这段等待时间会被统计为st,并且最终拉低应用吞吐、放大延迟。
一、先厘清概念:steal time为什么会产生
云服务器本质上是虚拟化环境,多个实例共享同一台宿主机上的物理CPU核心。虚拟化调度器会为每个实例划分时间片,但当物理核的总需求超过供给时,必然有一部分vCPU无法立刻获得执行机会。例如宿主机只有32个物理核心,却运行着100个vCPU,同时负载较高时,调度器只能让部分vCPU等待。等待时间越长,steal time占比越高。
在Linux系统中,/proc/stat文件中的cpu行第8列专门记录steal时间。top、mpstat、sar等工具会读取该字段,并计算为百分比展示。通常情况下,%st低于5%属于正常波动;5%到10%需要关注,说明已经存在轻微争抢;如果长期超过10%,多数业务会表现出明显的延迟上升。偶发飙到30%甚至50%时,说明宿主机已经出现比较严重的CPU抢占。
需要特别区分的是,steal time与iowait并不相同。wa表示等待磁盘IO完成的时间,st表示等待CPU调度的时间。如果看到wa很高,应该排查磁盘和文件系统;如果看到st很高,则要把重点放在宿主机资源争抢和虚拟化调度上。两者混为一谈会直接导致排查方向错误。
二、偷取时间偏高原因排行榜
根据云虚拟化平台的资源分配方式以及线上实例的表现,偷取时间偏高的原因可以按出现频率排成以下顺序。这个排行并非绝对,因为不同云厂商的底层实现存在差异,但它覆盖了绝大多数需要关注的场景。
- 第1名:宿主机CPU超卖过多。这是最常见的原因。云厂商为了提高物理资源利用率,通常会在一颗物理核上放置多个vCPU。如果超卖比例过高,所有实例都处于忙碌状态时,调度器无法满足每个vCPU的需求,st会持续偏高。这种场景的特征是自身进程CPU使用率不高,但
%st长期大于10%,且业务延迟与自身流量相关性不强。 - 第2名:邻居实例突发高负载。同样宿主机上的其他租户实例如果执行批量计算、压测、定时任务或忘记限流,会瞬间抢走大量物理CPU时间。这种场景的特征是
%st呈现周期性或突发的尖刺,和自己的业务请求波动时间不匹配。有时候白天正常,夜里某一时间段突然升高,往往就是邻居实例的定时任务导致。 - 第3名:超线程与CPU拓扑冲突。物理核心开启超线程后,一个核对应两个逻辑线程。如果云主机绑核策略不合理,多个vCPU被绑定到同一个物理核的逻辑线程上,或者网络中断处理与业务vCPU争抢同一个逻辑线程,也会导致调度等待时间增加。此时用mpstat按vCPU查看,常会发现某几个vCPU的
%st明显高于其他vCPU。 - 第4名:NUMA远端内存访问。当实例的vCPU和内存不在同一个NUMA节点上时,CPU访问内存的延迟会升高,进而降低有效利用率。虽然远端访问本身不直接计入steal,但它会让CPU在单位时间内完成的有效工作减少,从而加重调度队列拥塞,间接抬高偷取时间。特征通常是单核CPU看似较忙,但业务吞吐并没有相应提升。
- 第5名:自身vCPU数量或拓扑不合理。很多用户认为给云主机配置更多vCPU能提升性能,但实际上,如果应用不是高度并发型,增加vCPU只会让更多任务进入调度队列,同时增加宿主机侧竞争。某些情况下,把8核实例调整为4核后,st反而下降,业务延迟也更稳定。
三、用命令确认和量化st指标
排查偷取时间的第一步是确认%st的真实数值。top命令可以查看整体CPU状态,按数字1可以展开所有vCPU,但默认输出通常只显示聚合值。批量执行一次top命令,可以快速获得当前快照。
top -b -n 1 | head -n 5
如果怀疑不同vCPU之间存在不均匀的st,可以使用mpstat按CPU维度观察。mpstat -P ALL 1 5表示每秒输出一次,共输出5次,这样能看到短时间内的变化趋势。
mpstat -P ALL 1 5
sar也可以输出历史数据,适合事后分析。vmstat则更轻量,适合观察整体CPU状态。对于需要秒级以下粒度的场景,可以直接读取/proc/stat计算最近一秒的steal占比。下面是一个简单的Bash脚本示例。
#!/bin/bash
# 通过 /proc/stat 计算最近一秒的 steal time 百分比
prev_steal=0
prev_total=0
while true; do
cpu_line=$(grep '^cpu ' /proc/stat)
steal=$(echo $cpu_line | awk '{print $8}')
total=$(echo $cpu_line | awk '{print $2+$3+$4+$5+$6+$7+$8+$9+$10}')
delta_steal=$((steal - prev_steal))
delta_total=$((total - prev_total))
if [ $delta_total -gt 0 ]; then
st=$(echo "scale=2; 100 * $delta_steal / $delta_total" | bc)
echo "current steal time: $st%"
fi
prev_steal=$steal
prev_total=$total
sleep 1
done
执行这些命令时,建议同时运行一个稳定的测试负载,例如sysbench cpu run,观察是否存在CPU尚未跑满就出现高st的情况。如果自身业务压力很低时st仍然很高,基本可以确定是宿主机侧的资源争抢问题。
四、降低偷取时间的实操方案
确认问题之后,优先从实例生命周期和规格层面入手。第一选择是迁移实例。多数云平台提供实例迁移功能,迁移后可能会被调度到另一台负载更低的宿主机上。如果st长期高于10%,迁移实例往往是最快见效的方法。部分云厂商还支持自动热迁移,可以关注实例的底层宿主机状态。
第二选择是更换规格。如果当前使用的是共享型或突发性能实例,可以升级为独享型、CPU绑定型实例,或者干脆使用专用宿主机。独享型实例通常不会与大量租户互相争抢物理核,虽然单位价格更高,但对于延迟敏感型业务来说,稳定性提升很明显。
第三是从应用和系统配置上减少争抢。对于网络密集型应用,尽量开启网卡多队列,并将中断亲和性分散到多个vCPU,避免所有网络中断都集中在第一个核。下面是一个调整中断亲和性的示例。
# 查看网卡是否支持多队列 ethtool -L eth0 combined 4 # 查看中断号对应的CPU掩码 cat /proc/interrupts | head -n 20 # 将指定中断绑定到某个vCPU printf '2\n' | tee /proc/irq/28/smp_affinity
此外,如果应用不是大规模并发型,可以适当减少vCPU数量。减少vCPU后,单个vCPU获得的物理时间片会更充足,调度等待时间反而可能降低。绑定vCPU和内存节点也能减轻NUMA远端访问造成的性能损耗。
五、常见误区
第一个误区是把steal time当成自身业务负载。很多人看到st升高,就开始优化代码、增加缓存或者扩容CPU,但实际业务消耗的CPU并不高。st高说明问题主要出在宿主机或虚拟化调度层,优化应用代码几乎没有帮助。
第二个误区是把st和iowait混为一谈。wa高应该重点检查磁盘IO,例如查看iostat、iotop或文件系统写入情况;st高则要查看宿主机争抢和实例放置策略。错误地把st当作磁盘问题排查,会浪费大量时间。
第三个误区是只关注平均st。平均数值低并不代表没有争抢。邻居实例可能在很短时间内突然跑满CPU,导致你的服务出现偶发超时。建议使用秒级监控或者短周期mpstat输出,观察是否存在尖刺。对于线上核心业务,最好配置针对st的告警,一旦单核st超过阈值就触发迁移或人工介入。
第四个误区是盲目增加vCPU。在超卖严重的宿主机上,增加vCPU可能让实例内部产生更多的可运行任务,反而加剧对物理核的争抢。正确做法是先用mpstat确认是否存在单核瓶颈,再根据实际并发模型决定是加核还是换实例类型。把st控制在可接受范围,既需要云厂商的调度能力,也需要用户在规格选择和系统配置上做出合理决策。
CPU steal time云服务器偷取时间修改时间:2026-08-30 06:56:18