3684 字
约 12 分钟
19
S18-X20 · 容量规划与扩容决策

容量问题通常在两种时刻暴露:一次营销活动把 QPS 打到平时的五倍,或者某个表悄悄涨到两亿行,然后某天凌晨接口开始超时。两次都不是"突然",而是容量从来没被算过。

容量规划不是写一张好看的数字表,它要回答三个可操作的问题:现在能扛多少、什么时候会不够、扩容要多久生效。三个问题里最容易被忽略的是第三个——扩容时延决定了你必须在多早之前动手。


1. 三个问题与它们的输入

问题 需要的数据 输出形态
现在能扛多少 单实例容量 × 实例数 × 冗余扣减 当前可承载 QPS / 写入量
什么时候不够 流量增长趋势 + 峰值系数 触达阈值的时间点
扩容要多久 资源申请 + 启动 + 预热 + 导流 提前量(分钟/小时/天)

三个问题的输出必须能写成一句话:"当前容量 X,按当前增速在 T 之后触顶,扩容生效需要 L,所以必须在 T−L 之前启动。" 写不出这句话,说明规划还没做完。


2. 四个输入

输入 具体内容 常见错误
流量模型 均值、日峰、月峰、季节性、突发形态 只看日均,峰值按 1.5 倍拍
单请求消耗 CPU 时间、内存、IO、下游调用次数 用"经验值",不测
冗余要求 N+1 / N/2+1 / 跨可用区 只按 N 算,不留冗余
扩容时延 从决策到真正分担流量 假设"加机器就立刻生效"

四个输入缺一个,容量结论就不可信。尤其是冗余要求:按 N 算出来的容量,任何一台故障都会导致过载,而过载会引发雪崩式连锁。


3. 流量模型的建立

均值与峰值的关系不是固定倍数,而是由业务形态决定。同一系统的工作日峰值可能是均值的 3 倍,大促峰值可能是均值的 20 倍。

形态 特征 规划要点
常态波动 日内双峰(午间、晚间) 按日峰设计,冗余 1.3~1.5 倍
周期性季节 周末/月末/季度末偏高 找历史同期最高值,不用近 7 天
可预测突发 活动、开抢、定时任务 按预案峰值 + 预热,不靠弹性硬扛
不可预测突发 舆情、故障转移、重试风暴 需要限流与降级兜底
峰值系数 = 峰值 QPS / 均值 QPS        # 按最近 4 周同一时段核对,不要用全年平均
设计容量 = 峰值 QPS × 安全系数          # 安全系数按业务可容忍的降级程度定
增长外推 = 近 3 个月复合增长率(去掉单次活动带来的尖峰后)

两个细节:增长外推要剔除一次性活动,否则会把营销脉冲当成趋势;峰值系数要按同一时段比,拿凌晨均值除晚间峰值没有意义。


4. 单请求资源消耗的度量

资源 度量方式 关键点
CPU 单请求 CPU 时间(用户态 + 内核态) 用压测或 profile 采样,不用"感觉"
内存 常驻 + 每请求临时分配 关注 GC 压力,不只是峰值
IO 每请求读写字节数、IOPS 区分顺序/随机,二者成本差一档
下游调用 每请求调用次数与耗时占比 下游容量往往才是真瓶颈
单实例容量 ≈ 可用 CPU 核数 / 单请求 CPU 时间      # 理想上限,实际按 60%~70% 折算
并发需求   ≈ 目标 QPS × 单请求平均耗时(秒)      # Little 定律
下游压力   ≈ 目标 QPS × 每请求下游调用次数

第三条最常被漏算:应用能扩,数据库连接池与下游接口不一定能按同样比例扩。每请求调用次数乘以 QPS,才是下游真正要承受的量。


5. 瓶颈的判定顺序

容量规划的核心不是"算总量",而是找最紧的那一环。扩容非瓶颈环节,投入全打水漂。

判定顺序(从最容易饱和的开始逐层排除):
1. 接入层:连接数、带宽、TLS 握手 CPU
2. 应用层:CPU、GC、线程池队列长度、超时率
3. 数据层:连接池占用、慢查询、锁等待、复制延迟
4. 下游依赖:限流阈值、超时率、重试放大
5. 基础设施:磁盘 IOPS/吞吐、网络、文件句柄
现象 更可能是瓶颈在哪 验证方式
CPU 高且队列积压 应用层计算 看线程池队列与 GC 时间占比
CPU 不高但延迟线性上升 连接池/锁/IO 等待 看等待时间占比、连接池 active 数
应用扩容后延迟不变 数据层或下游 对比扩容前后下游耗时
高峰期超时集中在少数接口 下游限流或慢查询 按接口看 P99 与下游调用耗时

关键判断:扩容后指标不变,说明瓶颈不在被扩容的那一层。 这时继续加机器只会增加成本。


6. 垂直与水平扩容

方向 做法 上限与限制
垂直(scale up) 加 CPU/内存/更大机型 有单机上限;重启成本高;单点风险不变
水平(scale out) 加实例 要求无状态;需要负载均衡与会话外置

水平扩容的隐性前提容易被忽略:

  • 无状态:会话、本地缓存、上传临时文件必须外置;
  • 可均衡:长连接、粘性会话会让流量分布不均;
  • 可并发:定时任务、批处理在多实例下会重复执行,需要分布式锁或选主。
水平扩容前置检查:
[ ] 会话是否外置(Redis/DB,而不是本地内存)
[ ] 是否有本地缓存需要预热
[ ] 定时任务是否有选主/锁
[ ] 是否依赖本机文件或本机 IP
[ ] 启动时是否有全量加载(决定预热时间)

垂直扩容适合"有状态、难拆分"的组件,但它买到的是时间,不是架构——单机上限到了还是得拆。


7. 扩容时延的构成

扩容不是"点一下按钮"。真正的生效时间由五段串起来,任何一段被忽略,预算就会失准。

阶段 典型量级(按环境核对) 拖长的原因
申请资源 分钟级(预留池)到小时级(云上竞价/审批) 配额、审批、库存
启动进程 秒级到分钟级 依赖初始化、类加载
预热 分钟级 JIT、连接池、本地缓存、字典加载
注册与健康检查 秒级到分钟级 健康检查周期、就绪探针
流量导入 秒级到分钟级 负载均衡权重调整、连接重建
扩容生效时间 = 申请 + 启动 + 预热 + 注册 + 导流
# 若预热需要预热脚本/回放流量,单独计入
# 若走弹性伸缩,还要加"指标触发延迟"(监控采集 + 判定周期)

预热为什么不能省:刚启动的实例没有 JIT 编译、没有连接池、没有本地缓存,直接承接全量流量会表现为"新实例反而更慢",触发更多超时与重试,形成恶性循环。


8. 弹性策略

策略 触发依据 优点 局限
按指标弹性 CPU/队列长度/QPS 超阈值 自动化,成本可控 滞后:流量先到、扩容后到
预留缓冲 常备冗余实例 无滞后 成本固定
预测式扩容 历史周期 + 日历(活动/大促) 提前量足 依赖历史准确性
手动预案 活动前人工扩容 可控 依赖人记得

按指标弹性的滞后是结构性的:指标要采集、要跨过判定周期、要等实例就绪与预热,这几段加起来通常远大于一次流量尖峰的上升时间。所以弹性适合"缓坡",不适合"陡峰"。

可操作的组合:常备冗余覆盖日常波动 + 预测式覆盖已知活动 + 限流降级兜住未知陡峰。弹性只作为收尾微调。


9. 成本与冗余:N+1 与 N/2+1

冗余模型 含义 故障时剩余容量 成本
N 刚好覆盖峰值 0,任一实例故障即过载 最低,风险最高
N+1 多一台 可承受 1 台故障 中
N/2+1 按半数冗余 可承受近半故障 高
跨可用区 每个 AZ 独立满足 N+1 可承受单 AZ 故障 最高(含跨区流量成本)
例:峰值需要 10 台(N=10)
N+1     → 11 台,单台故障后仍余 10 台容量
N/2+1   → 10 台里最多容忍 5 台故障(剩余 5 台需能扛峰值 → 需按单台双倍容量设计)
跨 AZ   → 2 个 AZ 各 11 台 = 22 台(成本约翻倍,另有跨区延迟与流量费)

跨可用区的额外开销不只是机器数量:跨区调用延迟、跨区流量费、数据同步带宽都要计入。很多方案在纸面上只算了机器钱,上线后账单翻倍。


10. 压测与容量台账

压测是容量结论的唯一验证手段,不是上线前的仪式。它要回答三个具体问题:单实例极限在哪、扩容是否线性、瓶颈在扩到第几台时转移。

压测设计要点:
1. 阶梯加压:每档稳定运行 ≥5 分钟,观察是否进入稳态
2. 记录拐点:延迟开始非线性上升的那个 QPS,就是实际容量上限
3. 验证线性:扩 2 倍实例,容量是否接近 2 倍(不接近说明有共享瓶颈)
4. 观察下游:压测期间同步看数据库、缓存、第三方接口的指标
5. 记录降级点:限流/熔断触发时的 QPS 与错误率

容量台账把结论沉淀成可复核的表,而不是散落在聊天记录里:

字段 例
服务/接口 order-api / 列表查询
单实例容量 按最近一次压测核对
实例数 当前 / 冗余
峰值水位 最近 4 周最高
触顶预估 按增长率外推
扩容时延 分钟级(含预热)
复核日期 每季度或大活动前

11. 常见坑

坑 后果 改法
按均值算容量 峰值直接打爆 用峰值系数 × 安全系数
扩了应用没扩数据库 应用空转,延迟不变 按瓶颈顺序逐层验
忽略下游限流 自己扩了却被下游挡住 把下游容量纳入台账
弹性启动时间 > 降级窗口 扩容还没生效,用户已经跑了 常备冗余 + 预测式
按 N 设计冗余 一台故障即雪崩 至少 N+1
压测只压单接口 混合负载下的瓶颈没暴露 按真实流量配比压

12. 排错:五种"扩了但没用"

现象 原因 处理
加实例后 QPS 不涨 存在共享瓶颈(DB/锁/单点服务) 找共享资源,先解耦
新实例延迟比老实例高 没预热 加预热、延迟导流、就绪探针
高峰期扩容来不及 时延预算算错 改预测式 + 常备冗余
扩容后错误率反升 连接池/线程池未按实例调小,压垮下游 按实例数重算连接池上限
成本涨了容量没涨 扩的是非瓶颈层 回到瓶颈判定顺序

13. 边界:容量规划不解决什么

问题 能给答案吗 该用什么
某个慢查询怎么优化 不能(只给现象) 执行计划分析、索引设计
架构是否需要重构 不能(只给压力证据) 架构评审
成本该由谁承担 不能 成本分摊与账单标签
突发流量的具体形态 只能估 限流、降级、混沌演练

一句话:容量规划给出"需要多少",不给出"怎么变快"。 后者是性能优化与架构的事。


14. 自测

  1. 容量规划要回答的三个问题是什么?为什么"扩容要多久"最容易被忽略却最致命?
  2. 峰值系数为什么不能拿全年平均去算?增长外推要怎么剔除一次性活动?
  3. 每请求下游调用次数为什么必须乘以目标 QPS?漏算会导致什么?
  4. 扩容后指标完全不变,说明什么?下一步该查哪一层?
  5. 水平扩容的三个隐性前提是什么?
  6. 按指标触发的弹性扩容为什么不适合陡峰?替代组合是什么?
S18-X20 · 容量规划与扩容决策
https://www.clxhxhhr.top/posts/5942/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。