bigywater.tech
Docker · 40

CPU 节流:quota 用完后进程被暂停了多久

为什么容器的 CPU 用量明明没到上限,延迟却变高了?因为 cgroup 的配额是按周期算的,一个周期内用光配额就会被暂停到下一个周期。这篇用 cpu.stat 的 nr_throttled 和 throttled_usec,配合任务延迟,实测节流的表现。

71.7 ms vs 30.0 ms
30 ms 的任务在 --cpus 0.5 与不限制下的延迟中位数
188 ms
4 进程并行任务在 --cpus 1 下最慢的一次墙钟时间(不限制最慢 67 ms)
2622 ms
100 次 30 ms 任务在 --cpus 0.5 下累计被节流的时间

配额按周期算

实测 · 本机执行输出
  不限制:p50=30.0 p95=30.0 max=30.7 nr_periods=0 nr_throttled=0 throttled_ms=0
  --cpus 0.5(配额 50 ms / 周期 100 ms):p50=71.7 p95=77.2 max=79.2 nr_periods=60 nr_throttled=60 throttled_ms=2622
  --cpus 0.5,周期改成 10 ms(配额 5 ms / 周期 10 ms):p50=56.3 p95=59.4 max=60.4 nr_periods=601 nr_throttled=576 throttled_ms=2625

--cpus 0.5 是每 100 ms 周期最多用 50 ms CPU。30 ms 的任务第一个周期做完 30 ms 后,第二个任务在同一周期里只能再做 20 ms,剩下的要等到下一个周期;所以单次延迟 p50 到了 71.7 ms,100 次累计被节流 2622 ms。cpu.stat 里的 nr_throttled 和 throttled_usec 就是这个记录;没有设置限制时这两项是 0。

把周期改成 10 ms、配额 5 ms,同样是 0.5 个 CPU,总的被节流时间几乎一样(2625 ms),但单次延迟更短(p50 56.3 ms),因为每次等的时间更短。我没有测周期过小带来的调度开销。

短任务的尾部

实测 · 本机执行输出
  --cpus 0.5,5 ms 的任务:p50=5.0 p95=17.4 max=24.8 nr_periods=10 nr_throttled=10 throttled_ms=125

5 ms 的任务大多不被节流(p50 5.0 ms),但偶尔撞上周期边界,p95 到 17.4 ms,max 24.8 ms。平均 CPU 利用率不高,不代表没有延迟毛刺。

多进程

实测 · 本机执行输出
  不限制:10 次的墙钟时间 最快=44 中位=47 最慢=67 ms nr_throttled=0 throttled_ms=0
  --cpus 1:10 次的墙钟时间 最快=47 中位=64 最慢=188 ms nr_throttled=10 throttled_ms=1071
  --cpus 4:10 次的墙钟时间 最快=43 中位=48 最慢=68 ms nr_throttled=0 throttled_ms=0

4 个进程同时跑,一个周期内能把配额瞬间用光:--cpus 1 时 10 次全被节流,中位 64 ms、最慢 188 ms;配额给到 4 就没有节流,和不限制一样。多线程的服务设置过小的 --cpus,代价是尾部延迟。

分步演示

CPU 节流
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。测试程序是 python:3.12-alpine 里的脚本,用 time.thread_time 忙等指定的 CPU 时间并测墙钟延迟;节流计数来自容器 cgroup 的 /sys/fs/cgroup/cpu.stat 的增量(nr_periods、nr_throttled、throttled_usec);每种情形运行一次;虚拟机有 10 个 CPU,其它容器同时运行会带来一点噪声;实验后已删除容器和镜像
    • 没有验证:Kubernetes 的 CPU limit 与容器运行时的差别、内核 CFS burst(cpu.max.burst)、真实 Web 服务的延迟、Linux 宿主机上的不同内核版本、去掉限制或调大 --cpus 之后的最佳取值
    京ICP备2026067502号-1京公网安备11010502063487号