深色模式
水平扩展 vs 垂直扩展
加机器(scale out)还是加配置(scale up)?本文从成本、上限、改造成本、风险四个维度给决策依据,并给出"先这样再那样"的迁移路径。
适用环境
- 服务已在运行,监控数据完整
- 具备负载均衡(Nginx / SLB / Ingress)
- 有压测环境可验证扩展效果
bash
# 确认当前实例数与规格
kubectl get deploy order-api -o jsonpath='{.spec.replicas}{"\n"}'
kubectl get deploy order-api -o jsonpath='{.spec.template.spec.containers[0].resources}{"\n"}'1
2
3
2
3
操作步骤
1. 收集现状数据
promql
# 单实例 CPU / 内存水位峰值
max_over_time(process_cpu_seconds_total{process="order-api"}[7d:1m])
max_over_time(process_resident_memory_bytes{process="order-api"}[7d:1m])1
2
3
2
3
bash
# 是否有本地状态(决定能否水平扩展)
ls -l /var/lib/order-api/ 2>/dev/null
grep -rn 'session\|local_cache\|file' /etc/order-api/*.yml 2>/dev/null | head1
2
3
2
3
2. 做扩展性测试:多核线性度
bash
taskset -c 0 ./order-api & wrk -t1 -c50 -d30s http://127.0.0.1:8080/api | grep Requests/sec
taskset -c 0-3 ./order-api & wrk -t4 -c200 -d30s http://127.0.0.1:8080/api | grep Requests/sec1
2
2
4 核 QPS ≈ 1 核的 3.5 倍以上 → 垂直扩展有效;低于 2.5 倍 → 存在锁瓶颈,垂直扩展性价比低。
3. 做扩展性测试:多实例线性度
bash
kubectl scale deploy order-api --replicas=4
wrk -t8 -c400 -d60s --latency http://lb.example.com/api/order | grep -E 'Requests/sec|99%'1
2
2
对比 1 实例与 4 实例的总 QPS,接近 4 倍说明水平扩展有效(无共享瓶颈)。
4. 套用决策表
| 判断项 | 倾向 scale up | 倾向 scale out |
|---|---|---|
| 单实例 CPU 水位 | 低(<40%)但有单核打满 | 高(>70%)且均匀 |
| 架构 | 有状态、单体、强本地缓存 | 无状态、已容器化 |
| 扩展上限 | 需要内存 > 单机最大规格 | 需要超过单机规格上限 |
| 改造成本 | 零改造,重启即可 | 需引入 LB、会话外置 |
| 冗余收益 | 无(仍是单点) | 有(天然多副本) |
| 成本斜率 | 大规格单价溢价明显 | 线性,可精细调节 |
| 数据库 | 主从、难分片 | 已读写分离/分片 |
5. 常见组合路径
text
早期(QPS < 1000): scale up,最快最省事
中期(单机到顶): 改造为无状态 → scale out
后期(DB 到顶): 读写分离 → 分片 → 单元化1
2
3
2
3
6. 成本粗算(用相对值,不依赖具体单价)
text
设 4C8G 单价为 1 个单位,QPS 能力 600
方案 A:scale up 到 16C32G(约 4 倍单价)
能力通常 2.5~3 倍 → 单位 QPS 成本上升
方案 B:scale out 到 4 台 4C8G(4 倍单价)
能力接近 4 倍,且多 3 份冗余 → 单位 QPS 成本持平或更低1
2
3
4
5
6
7
2
3
4
5
6
7
用 单机QPS/规格单价 算单位成本,比值越高越划算。注意把冗余收益折算进 scale out 一侧。
验证
bash
# 扩展后重跑基线压测,对比三点
wrk -t8 -c400 -d60s --latency http://lb.example.com/api/order
# 1) 总 QPS 是否按预期倍数增长
# 2) P99 是否未恶化(扩展会引入网络跳转)
# 3) 错误率 < 0.1%1
2
3
4
5
2
3
4
5
常见坑
有状态服务直接横向扩容
本地 session、本地缓存、本地锁、定时任务在扩到多实例后会立刻出错。扩容前必须完成:session 外置(Redis)、缓存外置、定时任务选主、文件改对象存储。
扩容应用不打散数据库
应用层扩 10 倍、DB 连接数与写能力没跟上,最后 DB 成为瓶颈,整体吞吐不涨反降(排队加剧)。
垂直扩展需要停机
云主机升配一般要重启,物理机要停机插内存。生产单机场景必须先做主从切换演练,否则升级窗口就是一次计划外故障。
忽略 LB 自身容量
实例扩到几十台后,Nginx/SLB 的连接数与带宽会成为新瓶颈。大规模 scale out 要同步评估 LB 层。