想象你是一家即将开业的餐厅老板。别人看到的是一张菜单,而你焦心的是一组数字:每天会有多少客人走进来?午市和晚市会不会挤爆?后厨的灶台和厨师够不够用?多雇了厨师怕闲,少雇了又怕客人排队骂娘。这份厨房规划,本质上就是一次「容量规划」——而推理服务的容量规划,和开餐厅惊人地相似。 一个 AI 推理服务,就是一座数字餐厅:请求是客人,GPU 是灶台,模型是菜谱,QPS 是每秒进门的客流。容量规划要回答的问题只有两个:高峰期需要多少灶台(容量),以及如何让灶台在空闲时不浪费(弹性)。回答错了,要么服务超时被用户投诉,要么 GPU 空转烧钱。本文用「厨房经营手记」这条线索,带你从客流量预测、厨师出菜速度、灶台配置,一路走到排班表和月末复盘,完整掌握推理服务容量规划的六步方法。
学会推理服务容量规划,你就能在性能与成本之间精准拿捏,成为一个既能扛住流量洪峰、又不让 GPU 空转的云架构师。
可视化演示
展示最大池化与平均池化的运算过程,观察池化窗口如何对输入特征图进行下采样以减少空间维度。
本节配有交互动效(进入视口后自动加载,约 3KB)。
最大池化操作 池化窗口在输入特征图上滑动,选取每个窗口内的最大值作为输出 下采样减少空间维度,保留最显著的特征信息,降低计算量 out = max(I[2i:2i+2, 2j:2j+2])
需求分析预测
开餐厅之前,老板会在门口蹲一个星期,把每天的客流记下来:周一到周五几点有人、周末比平时多几成、对面写字楼入驻后中午会不会翻倍。没有这些数字,后厨的灶台要么不够用,要么闲着吃灰。推理服务的容量规划,第一步同样不是买 GPU,而是画出「客流天气预报图」。
推理服务里的「客流」就是每秒到达的请求数,业界叫 QPS(Queries Per Second)。线上网关和负载均衡器会记录所有历史请求,打开监控大盘,你能看到一条像心电图一样的流量曲线:白天高、凌晨低、大促时突然窜出尖峰。这些历史数据加上产品侧的预期,是容量规划的第一份输入。
实际操作中,我们会把历史 QPS 按天聚合,算出日均值,再乘以两个系数:业务增长系数来自季度目标或新客户接入计划,比如月增 8%、6 个月后就是 (1+0.08)^6≈1.59;高峰波动系数来自历史观测,比如一年中最忙的一天达到日常的 3 倍。两者相乘,就得到未来峰值 QPS 的预估值。
1. Q_avg 历史日均基线:取过去 30 天线上请求量的平均值,作为预测的起点
2. r 月增长率:业务侧给出的预期月增长,如 8%,代表需求的长期趋势
3. m 预测月数:本次容量规划面向的未来时间跨度,单位是月
4. f_spike 高峰波动系数:历史最高峰与日均值的比值,代表需求的尖刺程度
有了这张「流量天气预报图」,你才知道下个月的午市要不要加灶。记住,预测不是算命,而是用历史规律和业务信号把不确定性框在一个区间里——后面所有扩容策略,都建立在这个起点上。
性能基线测试
客流摸清了,再看自家的手艺。厨师一小时能颠多少道菜、蒸锅一次能出几笼,决定了同一时刻能接待多少桌。餐厅老板会在试菜日让厨师火力全开,记下每道菜的单位时间产量,这就是「性能基线」。
推理服务的性能基线来自压测。把写好的推理服务部署到一台 GPU 上,用压测工具(wrk、k6、locust)按不同并发数发请求,观测两个数字:吞吐量(QPS)和延迟(P50/P99)。P99 的意思是 99% 的请求都能在这个时间内返回,它代表最差的那批客人的体验。
压测结果通常呈现「先升后平」的曲线:并发太低,GPU 闲着,吞吐上不去;并发升高,吞吐跟着涨;到了某个临界点,吞吐不再增加,延迟却快速飙升——因为请求开始排队了。这个拐点的数值,就是单副本的容量锚点。吞吐、延迟、并发三者之间有一个经典关系式,叫 Little 定律:
1. C 并发请求数:同一时刻正在被 GPU 处理或排队等待的请求数量
2. L_avg 平均响应时间:单个请求从进入服务到返回结果的平均耗时,单位是秒
3. T 吞吐量:系统每秒能处理完的请求数,也就是 QPS
就像试菜日记录「一口灶一小时出 30 道菜」,压测记录的是「一张卡在目标延迟内能扛多少 QPS」。这份成绩单直接决定后面要买几块 GPU——压测数据不准,一切容量计算都是空中楼阁。
GPU资源度量
后厨的灶台有两个指标:能放几口锅,是容量;火有多旺,是功率。GPU 也有两个对应维度:显存容量和算力。菜谱再高级,锅放不下也白搭;锅放得下,火不够旺,客人还是得等。
先看显存。部署一个大模型时,显存占用主要来自三块:模型权重、激活值、KV Cache。权重占用的计算很简单:参数量乘以每个参数占的字节数。以 70 亿参数的模型为例,用 FP16 存储,2 字节一个参数,权重就要约 14GB。激活值随批大小变化,而 KV Cache 随并发请求数和序列长度线性增长,是推理场景特有的「隐形吃货」。如果模型大到一张卡放不下,还需要模型分片(张量并行、流水线并行),把权重切到多张卡上协同计算。
算力方面,单次前向推理的算力消耗约为 2×参数量×生成的 token 数(FLOPs 量级)。用 GPU 的峰值算力除以单请求消耗,再乘一个 0.3~0.5 的效率系数(因为内存带宽、算子调度都不完美),就能估算出理论吞吐上限。显存和算力,一个决定装不装得下,一个决定转不转得快,必须同时满足。
1. P 模型参数量:模型拥有的参数总数,如 70 亿
2. b 每参数字节数:权重存储精度,FP16 为 2 字节
3. M_act 激活值开销:前向计算过程中的中间结果,随批处理大小增长
4. M_kv KV缓存开销:缓存历史 token 的键值对,随并发数与序列长度线性增长
把灶台的「锅位」和「火力」都量清楚,才能回答「一块 GPU 能不能接住预期的客流」这个根本问题。很多容量事故,都始于只算了权重、漏了 KV Cache 这笔账。
QPS容量模型
餐厅的接待能力 = 座位数 × 翻台率。客流来了没有座位,只能门口排队;排队太长,客人扭头就走。推理服务也一样:请求到达后,要么立即被 GPU 处理,要么在队列里等待,等待超过客户端超时时间就直接失败。这个排队现象,正是容量模型的底层逻辑。
把需求侧和供给侧合到一起,就得到最核心的容量公式:所需副本数 = 峰值 QPS 除以单副本吞吐量,再乘上 (1+冗余率)。冗余率用来吸收流量抖动、单点故障和扩容期间的性能缺口,一般留 20%~30%。
排队论里更严谨的视角是 Little 定律:系统中的并发请求数 = 到达率 × 平均停留时间。反过来,当 P99 延迟目标定为 200ms、单副本能承受 32 个并发时,这个副本最多承载 32/0.2=160 QPS。这就是为什么压测基线和延迟目标共同决定了容量——你答应客人的上菜时间越短,需要的灶台就越多。
1. Q_peak 预测峰值QPS:来自需求分析预测的峰值流量
2. T_single 单副本吞吐量:来自性能基线测试的单卡容量锚点
3. r 冗余率:为抖动、故障、扩容延迟预留的富余量,如 0.3
4. 向上取整:副本数必须是整数,且宁多勿少,避免容量差一口气
这就像餐厅既按高峰客流配足餐位,又额外留两张应急桌应对突发。算出来的 N 不是最终答案,而是一个「有弹性的底线」——它告诉你常态下要准备多少灶台,也告诉你极端情况下扩容的边界在哪。
弹性伸缩策略
聪明的老板不会让所有厨师从早站到晚:午市前两小时叫钟点工,晚市结束让多余的人下班。推理服务的流量同样有潮汐,弹性伸缩就是那套自动排班系统:流量涨了自动加灶,流量跌了自动撤灶,让 GPU 利用率始终维持在一个健康区间。
最常用的实现是 Kubernetes 的 HPA(Horizontal Pod Autoscaler)。它周期性地读取自定义指标,比如 QPS、P99 延迟或 GPU 利用率,当指标连续超过目标值一段时间,就创建新副本;持续低于目标,则回收副本。为了避免指标抖动导致来回震荡,每次伸缩后都要进入一个冷却窗口,在窗口内不触发相反方向的伸缩。
HPA 的计算公式非常朴素:期望副本数 = 当前副本数 × 当前指标 / 目标指标。指标超过目标越多,扩容倍数越大。但弹性伸缩最大的坑是冷启动:新 Pod 要从镜像仓库拉取模型权重,加载到显存可能耗时几十秒甚至几分钟,就像钟点工要换衣服、找工位才能上手。等指标报警再扩容,客人早就排无可排。所以生产级方案都要加「提前扩容」——根据流量趋势预测 QPS 将达峰时先扩容,再配合模型预热和就绪探针,让新副本真正「接得住单」。
1. R_cur 当前副本数:上一时刻实际运行的 GPU 副本数量
2. M_cur 当前指标值:最近一个评估窗口内的实际指标,如当前 QPS
3. M_target 目标指标值:期望维持的指标水平,如单副本 70% 利用率对应的 QPS
4. 向上取整:多扩一个也比少扩一个安全,避免扩容后仍不够用
排班表要「提前看天气预报」,不能等客人排长队才打电话叫钟点工——冷启动的几十秒,就像钟点工换衣服进厨房的时间,客人已经等不及走了。
运维调优实践
餐厅开了半年,老板每周都会翻三张表:翻台率、排队时长、食材损耗。哪道菜翻台慢就改良,哪个时段人手紧就加人。容量规划从来不是开业前算一次就完事,而是「监控-压测-调优」的持续循环。
监控看板是容量规划的仪表盘,至少盯四类指标:入口 QPS、P99 延迟、GPU 利用率、扩容事件。每次发布新模型、升级框架,都要重新压测并回填基线,因为模型结构一变,性能基线可能就变了。成本优化则要定期核算 GPU 投入与有效请求量的比值,比如利用量化(INT8/FP8)降低显存、用 Spot 实例跑可中断任务。
其中 GPU 利用率是最关键的经营指标。利用率过低,说明灶台大多空闲,钱花得冤枉;利用率过高,说明风险在积累,峰值一到就会超时。实践中一般按利用率分档管理:低于 30% 缩容或与其他任务共享 GPU,30%~70% 是健康区间,超过 70% 就要检查扩容是否及时。用公式表达,利用率就是实际消耗算力与总供给算力之比:
1. Q_avg 平均QPS:一段时间内的平均请求速率,单位是请求/秒
2. t_infer 单请求GPU耗时:每个请求实际占用 GPU 的时间,单位是秒
3. N_gpu GPU总卡数:当前可供调度的 GPU 数量
月末复盘时,老板会调整下周的排班表;运营同学也会根据监控数据调整伸缩阈值、优化模型量化。容量规划是一场没有终点的精进——每一次调优,都是为了让 GPU 这块「灶台」烧得更旺、更省。
AI 应用场景
大模型API平台的弹性扩容
阶段:容量规划与弹性伸缩
解决的问题:传统方式固定部署 N 台 GPU,流量低谷时闲置浪费、高峰时集体超时;AI 方式通过 QPS 容量模型确定基线副本数,再叠加 HPA 自动伸缩,像餐厅按客流自动增减钟点工一样,实现性能与成本平衡。
具体案例:某 SaaS 公司提供 7B 模型的对话 API,白天企业调用高峰 QPS 5000,夜间跌到 300。容量规划算出基线 40 卡,HPA 在 QPS 超过阈值时自动加卡到 60,夜间缩回 25,GPU 整体利用率从 25% 提升到 55%。
电商大促前的容量预估
阶段:需求分析预测
解决的问题:大促流量无法凭经验拍脑袋,AI 方式用历史 QPS + 增长系数 + 高峰系数预测峰值,提前两周备好 GPU 实例,相当于餐厅提前预定周末的食材和钟点工。
具体案例:双 11 前,团队统计去年大促的 QPS 尖峰是日均的 6 倍,叠加会员增长 20%,预估值 = 日均 × 1.2 × 6。据此预订抢购时段的高性能 GPU 实例,活动期间 P99 延迟稳定在 180ms,无一次扩容事故。
GPU成本治理与FinOps
阶段:运维调优与成本优化
解决的问题:多团队共享 GPU 集群利用率参差不齐,AI 方式通过利用率分档和弹性伸缩回收空闲资源,就像餐厅根据翻台率调整每张桌子的使用效率。
具体案例:某 AI 中台团队给三个业务线分配 GPU,通过监控发现 A 线利用率只有 15%,B 线晚高峰超 80%。优化后,A 线缩容并共享 Spot 实例,B 线配置自动扩容,整体 GPU 预算下降 40%。
Python 演示
"""推理服务容量规划工具:预测峰值QPS,计算副本数,模拟HPA伸缩决策."""import math def predict_peak_qps(qps_avg, growth_rate, months, spike_factor): """峰值 = 日均基线 x 增长系数 x 高峰波动系数.""" growth = (1 + growth_rate) ** months return qps_avg * growth * spike_factor def single_replica_capacity(concurrency, avg_latency_ms): """Little定律:吞吐量 = 并发数 / 平均响应时间.""" return concurrency / (avg_latency_ms / 1000.0) def required_replicas(peak_qps, single_capacity, redundant_ratio): """容量模型:副本数 = 峰值QPS / 单副本吞吐,再乘(1+冗余率).""" return math.ceil(peak_qps / single_capacity * (1 + redundant_ratio)) def hpa_desired_replicas(current_replicas, current_metric, desired_metric): """HPA:期望副本 = 当前副本数 x 当前指标 / 目标指标.""" return math.ceil(current_replicas * current_metric / desired_metric) if __name__ == "__main__": avg_qps = 1200.0 peak = predict_peak_qps(avg_qps, growth_rate=0.08, months=6, spike_factor=3.0) print("预估峰值QPS:", round(peak, 1)) per_replica = single_replica_capacity(concurrency=32, avg_latency_ms=200) replicas = required_replicas(peak, per_replica, redundant_ratio=0.3) print("单副本吞吐量:", round(per_replica, 1), "QPS") print("建议GPU副本数:", replicas) surge_qps = peak * 1.25 desired = hpa_desired_replicas( current_replicas=replicas, current_metric=surge_qps, desired_metric=per_replica * replicas * 0.8, ) print("流量超预期25%时,HPA期望副本数:", desired)
growth = (1 + growth_rate) ** months把月增长率按幂运算换算成 m 个月后的总增速,相当于 6 个月每月涨 8% 的复利效果。return concurrency / (avg_latency_ms / 1000.0)Little 定律的代码形态:先把毫秒转成秒,再用并发数除以平均延迟得到单副本吞吐量。math.ceil(peak_qps / single_capacity * (1 + redundant_ratio))容量模型落地:向上取整保证副本数充足,冗余率给运营留出缓冲。return math.ceil(current_replicas * current_metric / desired_metric)HPA 公式:指标超目标时按比例放大副本数,是自动伸缩的核心引擎。surge_qps = peak * 1.25人为模拟「流量比预期多 25%」的突发场景,验证这套容量规划是否还有余量应对意外。
常见误区
误区我统计了线上一天的平均 QPS 是 800,按这个数字买了两块 GPU,结果一到大促全部超时,用户一直在转圈。
正解平均数是容量规划的头号陷阱。流量是波动的,平均 QPS 会掩盖 10 倍的高峰尖刺。正确做法是用峰值和 P99 延迟来规划,即在日均基础上乘高峰波动系数。就像餐厅按午市峰值客流备灶,而不是按一天 24 小时的平均客流,否则饭点一定挤爆。
为何常见:平均值最容易获取和计算,监控大盘默认展示的也是平均值,人们自然用它做决策,却忽略了流量的分布形态。
误区模型能加载到 GPU 上就说明跑得动,我只关心显存够不够装模型权重。
正解推理是显存和算力的双重约束。连续生成时 KV Cache 会随并发快速增长,同时算力打满时延迟会飙升。评估时要同时验证明存峰值占用和 GPU 利用率,两者都在安全区间才算通过,就像灶台既要放得下锅,也要火够旺。
为何常见:模型加载是部署的第一道门槛,跨过它给人「已经成功」的错觉;而 KV Cache 是运行时才显现的成本,静态检查根本看不到。
误区反正有 HPA 自动扩容,QPS 涨了它自己会加副本,我不需要预留 buffer。
正解HPA 的扩容有天然的滞后性:指标采集、评估窗口、新 Pod 调度、模型加载都耗时,从流量突增到新副本真正服役往往要好几分钟。事前容量规划负责保证「常规峰值能扛住」,弹性伸缩只负责应对「计划外的波动」,两者是配合关系,不是替代关系。
为何常见:云厂商宣传「自动伸缩」让很多人误以为是即时反应,低估了冷启动的延迟,就像以为钟点工一个电话就能立刻出现在厨房里。
误区流量一降下来,我立刻把副本数缩到最少,这样可以最大程度省钱。
正解缩容太快会导致副本数在阈值附近来回震荡:扩两个、缩一个、再扩三个,每次伸缩都有额外调度开销,还可能把正在排队的请求掐断。正确做法是设置冷却窗口和最小副本数,让伸缩动作稳定下来,就像餐厅不会因为午市一过就把所有厨师赶回家,还要为晚市留人。
为何常见:成本焦虑让人倾向于「最省」策略,却忽略了频繁伸缩本身的稳定性开销,反而浪费更多资源。
面试题
Q1. 推理服务容量规划的第一步最应该做什么?
- A.直接采购最强GPU硬件
- B.分析历史流量与增长← 正确答案
- C.立即开启全自动伸缩
- D.部署模型并灰度上线
答案:B。容量规划的第一步是摸清需求,就像餐厅先观察客流再定灶台。采购 GPU、开启伸缩、部署模型都是后续动作,没有需求预测,它们都无从谈起。
Q2. 根据Little定律,吞吐量QPS的计算方式是?
- A.并发请求数乘以平均延迟
- B.并发请求数除以平均延迟← 正确答案
- C.平均延迟除以并发请求数
- D.并发请求数加上平均延迟
答案:B。Little 定律 T=C/L,吞吐量等于并发数除以平均延迟。乘、除反、加都是错误的运算关系,相当于把翻台率算成了上菜速度的乘积。
Q3. 70亿参数模型以FP16存储,模型权重约占多少显存?
- A.约3.5GB显存容量
- B.约7GB显存容量
- C.约14GB显存容量← 正确答案
- D.约28GB显存容量
答案:C。70 亿参数 × 2 字节 = 140 亿字节 ≈ 14GB。3.5GB 是 INT4 量化后的量级,7GB 是误把参数量当 GB 数,28GB 是把每个参数按 4 字节计算得出。
Q4. 推理服务中随并发数和序列长度增长最明显的显存开销是?
- A.模型权重参数
- B.前向激活值
- C.KV缓存区← 正确答案
- D.框架运行日志
答案:C。模型权重加载后是固定占用,激活值随批大小变化较小,KV Cache 随并发数和序列长度线性增长,是推理场景的「隐形吃货」。日志与显存无关。
Q5. HPA计算期望副本数时使用的公式是?
- A.当前副本乘以目标除以当前指标
- B.当前副本乘以当前指标除以目标← 正确答案
- C.目标指标乘以当前副本除以冗余
- D.当前指标除以目标再乘以冗余率
答案:B。HPA 公式是期望副本 = 当前副本 × 当前指标 / 目标指标。把当前指标除以目标指标,就是「超了多少就扩多少倍」,对应排班表上客流翻倍就加一倍人手。
Q6. 压测时吞吐量随并发升高出现「先升后平」的拐点,此时最准确的理解是?
- A.系统已达最大吞吐,再加压延迟会飙升← 正确答案
- B.系统出现死锁,需要重启恢复服务
- C.GPU显存不足,需要更换更大显存
- D.压测工具失效,需要更换压测工具
答案:A。拐点意味着系统已经满负荷,请求开始排队,P99 延迟即将飙升。这个拐点正是容量模型中单副本吞吐量的取值点,不是故障信号,也不是显存或工具问题。
Q7. 容量公式中冗余率(如30%)的主要作用是什么?
- A.提高GPU硬件采购预算
- B.抵御流量抖动与故障波动← 正确答案
- C.提升GPU平均利用率
- D.让监控图表更加美观
答案:B。冗余率是为流量抖动、实例故障和扩容延迟预留的缓冲,相当于餐厅的应急桌位。它不是为了提升利用率,反而会稍微降低利用率。
Q8. 以下哪些是推理服务容量规划的输入数据?
- A.历史QPS流量画像← 正确答案
- B.单副本压测基线← 正确答案
- C.代码仓库提交记录
- D.业务增长预期数据← 正确答案
答案:ABD。容量规划输入包括历史流量画像、压测基线和业务增长预期。代码仓库提交记录反映开发进度,与线上请求容量没有直接关系。
Q9. 缓解弹性伸缩冷启动问题的合理手段有哪些?
- A.基于流量趋势提前扩容← 正确答案
- B.将评估窗口缩短到几秒
- C.模型预热与就绪探针← 正确答案
- D.完全关闭自动缩容策略
答案:AC。提前扩容和模型预热能缩短新副本「上菜」的时间;缩短评估窗口会让伸缩抖动加剧,完全关闭缩容则持续浪费成本,两者都不合理。
Q10. GPU利用率长期高于70%,可能预示哪些问题?
- A.GPU算力得到了充分使用
- B.高峰来临时存在超时风险← 正确答案
- C.容量规划制定得过于保守
- D.需要检查扩容是否及时← 正确答案
答案:BD。利用率长期偏高说明资源紧绷,高峰来临时容易超时,需要检查扩容是否及时。充分利用本身不是问题,但「长期」偏高意味着风险积累;规划保守恰恰会导致利用率偏低,而非偏高。