返回博客
2026年8月31日Sergei Solod7 分钟阅读

即使没有流量,我的 REGXA VPS 仍出现了 94% 的 CPU Steal

在排查 REGXA KVM VPS 的严重性能问题时,我测到 92–94% 的 CPU steal、耗时数秒的 localhost 请求、不断增长的连接队列,以及超过两分钟才返回的 HTTP 504。移除全部生产流量后,CPU steal 反而升到 94.17%,REGXA 随后将其归因于共享基础设施上的资源争用。

REGXAVPSLinuxCPU steal虚拟化

我写这篇文章并不是为了给 REGXA 写一篇负面评价,也不是想告诉别人该不该购买他们的 VPS。这只是我作为开发者经历的普通一天。

我把正常 workload 迁移到一台 2 vCPU、2 GB RAM、60 GB NVMe 的 KVM VPS。Nginx 正常运行,backend 也正常运行,但整台机器却像严重过载一样:请求不断堆积,TLS 操作变慢,连接长期保持打开,一些请求最终要等两分钟以上才返回 HTTP 504。

CPU accounting 改变了排查方向

我最初的判断很直接:VPS 内部一定有某个进程在吃 CPU。于是我运行了 mpstat

Average CPU steal: 92.58%
CPU 0 steal: 90.62%
CPU 1 steal: 94.57%
CPU user: 4.02%
CPU system: 1.47%
CPU iowait: 0.41%
CPU idle: 0.53%

单独的采样反复显示大约 89–98% 的 steal。CPU pressure 也非常高:

CPU PSI some avg10: 79.47
CPU PSI some avg60: 75.32
CPU PSI some avg300: 76.31
Load average: 5.85 / 5.75 / 5.73

这只是一台两 vCPU 的虚拟机。Linux 中有 runnable process 在等待 CPU。真正关键的指标不是普通的 application CPU usage,而是 %steal

CPU 使用率高和 CPU steal 高是两种不同的问题

如果真的是我的 application 在消耗处理器,我应该看到很高的 usersystem。但这台 VPS 大致是这样的:

user: 4%
system: 1%
steal: 93%

CPU steal 指的是 virtual CPU 已经准备好执行,但 hypervisor 没有给它安排执行的时间。因此,当我说 VPS 的 CPU time 被拿走时,我指的是虚拟化中的这个技术含义。我无法证明 REGXA 有意把原本独占属于我的 physical core 分给了其他客户,也无法通过 guest metrics 推断意图。我能证明的是,guest 反复有任务等待执行,却拿不到 CPU scheduling time。

我移除了全部生产流量

这时仍然存在一个合理的反驳:也许问题就是我的 workload 引起的。所以我把这个变量去掉了。我把 active workload 移到其他服务器,停止所有到这台 VPS 的 production traffic,等队列清空后再次进行同样的测量。

Average CPU steal: 94.17%
CPU 0 steal: 95.56%
CPU 1 steal: 92.83%
CPU user: 1.95%
CPU system: 0.59%
CPU iowait: 0.59%
CPU idle: 2.18%

结果反而更差。单独的 vmstat 样本仍然显示 91–98% 的 steal,最多有 15 个 runnable process 在等待 CPU。最关键的组合是:

user: 1.95%
system: 0.59%
steal: 94.17%

这时我的 application 几乎什么都没做,但 VM 依然失去了几乎全部 scheduling time。正常的生产负载已经无法合理解释这个现象。

甚至 localhost 都慢得离谱

我还通过 127.0.0.1 测试 HTTPS,这样就把公共 DNS、我的 ISP、地理距离以及外部网络路径全部排除在测试之外。

有流量时,10 次 localhost HTTPS 请求中有 4 次在 TLS handshake 阶段失败。成功的请求分别耗时 29.30、22.77、12.25、11.87、11.12 和 9.40 秒。有些 TLS handshake 本身就用了大约 9 秒。

移除 production traffic 后,localhost 有所改善,但依然极不稳定:0.061、0.745、0.830、0.873、1.010、1.117、1.121、2.188 和 3.355 秒。同一个本地操作一次可能只需要约 61 ms,下一次却可能超过 3.3 秒。

整个 stack 都出现了连锁反应

某个时刻,我看到大约 450 个 established connection、122 个 orphaned connection、110 个 FIN-WAIT-1 和 33 个 CLOSE-WAIT。localhost backend 的 listen queue 达到约 14–15,HTTPS queue 达到约 40。

Nginx 记录了在 142.857、138.902、135.064、129.819 和 128.657 秒后返回的 HTTP 504。其他请求保持打开约 67–130 秒。我还看到了大约 35–41 秒的 secure-connect timeout、database network timeout 以及延迟的 TLS 操作。

如果分开看,这些症状很容易被认为是 Nginx、数据库、网络或 backend 的不同问题。但把 timeout 调大,并不能创造 hypervisor 没有 schedule 给你的 CPU time。

RAM 和磁盘无法解释问题

VPS 仍有大约 1.0–1.1 GiB 可用 RAM,几乎没有使用 swap,没有 OOM event,也没有 OOM killer 活动。文件系统只使用了大约 20%,还有大约 44 GB 可用。在关键 CPU 测量期间,I/O wait 一直低于 1%。

内存没有耗尽,磁盘没有满,我的 application 也没有消耗那部分缺失的 CPU。最突出的指标依然是 %steal

正常的 KVM VPS 完全是另一种表现

我在另一台正在处理正常流量的 KVM VPS 上进行了同类型的测试:

Average CPU steal: 0.02%
CPU idle: 87.86%
CPU PSI avg10: 0.29
CPU PSI avg60: 0.63
CPU PSI avg300: 0.49
Load average: 0.47 / 0.33 / 0.14

它的 10 次 localhost HTTPS 请求都在大约 37–69 ms 内完成。后来我还测试了另一台确实很忙的 production VPS,当时 user CPU 为 61.71%,system CPU 为 5.08%,idle 为 24.09%,而 steal 只有 0.13%。

现在我最看重的就是这种区别。一台 VPS 可以因为我的软件真的在使用 processor 而很忙。这和 guest 把超过 90% 的已测 CPU time 用在等待 hypervisor 上完全不是一回事。

REGXA 最终确认了基础设施层面的资源争用

从 VM 内部,我能测量 guest,但看不到 physical host、scheduler configuration、CPU quota 或邻近 VM。REGXA 可以看到这些信息。

支持团队最终告诉我,这台 VPS 运行在 shared CPU infrastructure 上,CPU resource 会在多台 virtual machine 之间共享,performance 会随着 physical node 的负载变化。他们还表示 Frankfurt infrastructure 当时需求特别高,并明确将我观察到的高 CPU steal 归因于 resource contention on the underlying infrastructure

他们还表示,当前 infrastructure 上无法修改这台 shared VPS 的 CPU quota 或 scheduling policy,也无法额外分配 dedicated CPU resource。提出的技术方案是把 VPS 迁移到 utilization 更低的 location。

这个解释很难和我之前看到的 dedicated CPU cores、guaranteed resources 等产品措辞对应起来。我无法查看 exact host configuration,所以不能断定直接机制究竟是 CPU overcommitment、quota、scheduler weighting、throttling,还是多种因素的组合。我也无法证明主观意图。但这并不重要:Linux 持续显示 92–94% steal,而 REGXA 自己也把这个异常值归因于 shared infrastructure 上的 contention。

退款也需要继续争取

基础设施问题明确后,我不想继续把 VPS 迁移到不同 node 上测试。我想取消 service 并拿回自己的钱。

最初对方只愿意退一部分金额,而且提出的 refund 是退到 REGXA account balance,而不是退回我付款使用的银行卡。对我来说,如果我正在退出这项 service,provider credit 并不等同于真正的退款。

所以我继续沟通,坚持要求将 100% 的付款退回 original payment method。最终 REGXA 同意了,并把全部金额退回原始支付方式,同时把这次 full refund 描述为一个 exception。

我认可他们最终确实退回了全部金额。但在支持团队已经确认 infrastructure contention 之后,我仍然需要继续推动才能解决退款问题,这也是整个经历的一部分。

这件事给我留下的经验

最容易犯的错误,就是继续优化 application。我本可以修改 Nginx、增加 timeout、降低 concurrency、添加 retry、调查 MongoDB,或者重写 backend。某些改动可能会改变部分症状,但都无法回答最重要的问题:为什么 CPU steal 超过了 90%?

现在我不会只检查 SSH 是否正常、Nginx 是否启动、health endpoint 是否返回 200。对于新的 VPS,我还会检查 %user%system%iowait%idle%steal、CPU PSI、run queue 和 localhost latency。

如果情况可疑,我会移除 workload 再测一次。在这次事件中,这一步给出了最清楚的结果:

CPU user: 1.95%
CPU system: 0.59%
CPU steal: 94.17%

我并不是说所有 REGXA VPS 都会这样。我测试的是一台 VPS,并记录了发生在它身上的事情。但在这台机器上,证据非常清楚:我的 application 几乎没有使用 CPU,而 Linux 却显示绝大部分 virtual CPU time 都消耗在等待 hypervisor scheduling 上。REGXA 后来又把同样的行为归因于其 shared infrastructure 上的 resource contention。

这就是我记录这件事的原因。不是为了打分,也不是为了推荐或劝退,只是开发者工作中的一天,以及一个我以后在任何 VPS 上都不会再忽略的 metric。