深色模式
CPU 容量评估
CPU 容量不是"用到 100% 才扩"。本文教你用利用率水位和线性度两个维度,算出 CPU 的真实承载上限与安全扩容点。
适用环境
- 已部署 node_exporter 与 Prometheus
- 服务进程可观测(process_exporter 或 cAdvisor)
- 已知服务实例的 CPU 核数(物理机或容器 limit)
bash
# 确认采集正常
curl -s 'http://localhost:9090/api/v1/query' \
--data-urlencode 'query=count(node_cpu_seconds_total{mode="idle"}) by (instance)'1
2
3
2
3
操作步骤
1. 算整机 CPU 使用率
promql
# 整机使用率(0~1)
1 - sum(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)
/ count(node_cpu_seconds_total{mode="idle"}) by (instance)1
2
3
2
3
2. 算进程级 CPU 使用核数
promql
# 某进程用了多少核
sum(rate(process_cpu_seconds_total{process="order-api"}[5m]))1
2
2
bash
# 本机快速核对(%CPU 是单核百分比,除以核数才是整机占比)
top -bn1 -p "$(pgrep -f order-api | head -1)"
nproc1
2
3
2
3
3. 测线性度:加压看 QPS 是否跟着涨
bash
for c in 20 40 80 160; do
printf 'c=%s ' "$c"
wrk -t2 -c"$c" -d30s http://10.0.0.11:8080/api/order | grep 'Requests/sec'
done1
2
3
4
2
3
4
把 (并发, QPS, CPU%) 三元组记下来:
| 并发 | QPS | CPU% | 每 1% CPU 的 QPS |
|---|---|---|---|
| 20 | 300 | 25% | 12 |
| 40 | 590 | 50% | 11.8 |
| 80 | 1000 | 85% | 11.8 |
| 160 | 1050 | 98% | 10.7 |
每 1% CPU 的 QPS 保持恒定即为线性;开始下降说明进入饱和区(锁竞争、上下文切换、GC)。
4. 判断饱和原因
bash
# 上下文切换暴增 → 线程过多或锁竞争
vmstat 1 5 | awk '{print $1, $12, $13}'
# CPU 花在内核态 → 系统调用/网络栈开销
top -bn1 | grep -E '^%Cpu'1
2
3
4
2
3
4
5. 计算容量结论
text
线性区上限 CPU% = 85%(超过则延迟陡增)
单机可用 QPS = 线性区 QPS ÷ 安全水位 0.7
= 1000 × 0.7 ≈ 700 QPS
需要核数 = ceil(峰值 QPS ÷ 单机可用 QPS) × 每机核数1
2
3
4
2
3
4
6. 多核扩展性修正
bash
# 分别限制 1/2/4 核压测,看 QPS 是否线性翻倍
taskset -c 0 ./server & # 1 核
taskset -c 0,1 ./server & # 2 核
taskset -c 0-3 ./server & # 4 核1
2
3
4
2
3
4
若 4 核只有 1 核的 2.5 倍,说明存在锁或共享资源瓶颈,此时应优先做水平扩展而非加核。
验证
promql
# 峰值时段整机 CPU 最高水位应 ≤ 70%
max_over_time(
(1 - sum(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)
/ count(node_cpu_seconds_total{mode="idle"}) by (instance))[1d:5m]
)1
2
3
4
5
2
3
4
5
常见坑
把 load average 当 CPU 使用率
load 包含等待 IO 的进程,load 8 在 4 核上可能是 IO 问题而非 CPU 不够。判断 CPU 容量必须看 CPU 时间占比。
容器里看宿主机 CPU
容器内 top 看到的是宿主机核数,进程占比会被稀释。要用 container_cpu_usage_seconds_total 或 cgroup limit 计算。
只看平均核数
8 核机器平均使用 50%,但可能是单线程瓶颈打满 1 核、其余空闲。必须看 max by (cpu) 判断是否单核打满。
突发型服务按峰值配置
CPU 曲线是尖刺型(每天只有 5 分钟高峰)却按峰值常备,浪费严重。这类应交给弹性伸缩,而不是常备容量。