Skip to content

推理服务设计 ​

"设计一个支持 10 万 QPS 的大模型推理服务"——先拆题:10 万 QPS × 平均输出 200 token ≈ 每秒 2000 万 token 的生成流水。这不是一台机的事,是一个系统的设计题。本篇按容量 → 路由 → 质量 → 成本的顺序给参考答案。

第一步:容量与部署形态 ​

算卡是第一道算术:单卡 7B 模型 decode 约 3000 token/s(带宽账见[芯片架构]篇),2000 万 token/s ≈ 数千卡起步——这决定了服务必须是多实例 + 水平扩展的。单实例内的并发靠 continuous batching(见[推理引擎]章),实例数 = 总需求 ÷ 单实例 goodput(不是峰值吞吐——要留 SLO 余量与发布余量)。

部署形态的三个决策点:

  • 实例规格:TP 度数按模型大小定(7B 单卡/TP2,70B TP4–8),同 TP 组必须同超节点(通信账见[超节点]篇);多实例复制走 DP,prefix cache 命中率与"会话亲和"在此权衡(见下文路由)。
  • P/D 分离:QPS 高且 prompt 长的服务几乎必选(见[P/D 分离]篇)——prefill 实例池与 decode 实例池独立扩缩容,是不同资源形态(计算型 vs 带宽型)的分池。
  • GPU 共享与虚拟化(题库 135/238):多模型混部小模型时用 MIG/时间片/MPS 做 GPU 切分,换来利用率;代价是隔离性(显存 OOM 串扰、性能噪声)。原则:SLO 硬的服务独占,best-effort 的才共享。

第二步:路由与准入 ​

请求路由(题库 239)的层级:网关 → 负载均衡 → 实例选择。LLM 特有的一层是会话/前缀亲和:同一会话的请求打到同一实例可命中 prefix cache(省掉整段 prompt 重算),但会让负载倾斜(长会话粘住实例)。工程解法是前缀感知路由:按最长公共前缀哈希选实例池,池内再按实时负载调度——SGLang/vLLM 生态的路由器都实现了这一层。

Admission control(题库 250):与其让所有请求挤进队列把 P99 拖爆,不如提前拒绝/降级:实例层看 KV Cache 水位与队列长度(超过阈值即返回 429 + Retry-After),平台层做排队与配额。LLM 请求的"先占坑后付账"特性(KV 随生成增长)让准入必须按预测峰值占用而非当前占用——一个 max_tokens 很大的请求现在只占一点,未来可能吃掉整个实例。

长请求的抢占(题库 137):decode 可被抢占(KV 换出到 CPU/重算),用于保 SLO 级请求的延迟——抢占成本 = KV 重算或换页时间,换页(recompute 与 swap 的选择)在[请求调度]篇推导过。

第三步:SLO 与质量 ​

**Latency SLO(题库 249)**的工程化:把" TTFT < 2 s、TPOT < 50 ms、P99"写成 admission 与调度的硬约束——超 SLO 的请求宁可早拒绝。streaming(题库 242)是体感 SLO 的关键:逐 token 下发让用户感知延迟 = TTFT 而非全时长,网关层要做 SSE/WebSocket 的连接管理与断线重连(KV 未过期时重连可续写)。

结果缓存(题库 243):确定性/低风险场景(分类、摘要类目)可缓存完整响应,key = 归一化 prompt + 参数;与 prefix cache 互补(一个省 decode、一个省 prefill)。

A/B 与 canary(题库 133/241):按会话(不是请求)分流——同一会话混用模型会造成上下文风格跳变;指标看 goodput 与业务指标的双侧检验;canary 先按流量比例灰度,叠加 shadow 模式(新模型跑影子流量不看结果先看性能)。

安全与护栏(题库 245/254):输入侧(注入检测、敏感词)与输出侧(合规过滤)的 guardrail 是延迟预算的一部分(每个过滤环节几十 ms 要计入 TTFT);安全方面:租户隔离(网络/配额)、审计日志、模型与 prompt 的机密性(prompt 泄露防护)。

第四步:成本与弹性的收尾 ​

Auto-scaling(题库 113/237):指标不能只用 QPS——用 KV Cache 水位或并发 token 数扩缩容(它们才正比于显存压力);扩容慢(拉起+加载权重分钟级)决定了必须基于预测的提前扩容,缩容则要慢(防抖)。实时与离线统一(题库 253):在线服务的低峰资源承接离线批量任务(离线评估/数据生成),靠优先级抢占实现——这是推理平台利用率的最大单项杠杆。

**Cost optimization(题库 144/247)**的清单:实例利用率(batching/分离)、模型档位降级(简单请求路由到小模型——cascade/ensemble 架构,题库 251)、量化(W4/FP8)、spot 资源跑 best-effort、以及多 region 的容量套利。

**Edge 部署(题库 145/240/248)**的答题要点:模型缓存(边缘节点的模型分发与版本管理)、与云的协同(小模型本地兜底 + 大模型云端)、弱网与离线语义(队列与最终一致)。它通常不是"更小的云",而是另一套约束(内存/能耗优先,见[推理引擎版图]篇)。

多租户配额与隔离(题库 143)的展开

三层配额:网关层 QPS/token 限流(令牌桶,按租户计费口径);实例层 KV Cache 与并发槽的 reservations(防止一个租户的洪峰挤占他人 SLO);集群层 节点池/优先级配额(类似训练平台的多租户,见[训练平台设计]篇)。隔离性预算:共享实例的 batching 天然让租户间延迟互相影响("noisy neighbor"),硬隔离要么物理分池要么 GPU 虚拟化——按租户 SLO 档位选择隔离强度。统计上要暴露每租户的 goodput 与被拒率,配额调整才有依据。

小结 ​

  • 先算容量:goodput 口径估卡数;部署形态的三个决策是 TP 度数、P/D 分离、GPU 共享边界。
  • 路由的 LLM 特色是前缀亲和;准入按预测峰值 KV 占用;抢占是保 SLO 的最后手段。
  • SLO 用分位数 + streaming 体感兑现;A/B 按会话分流;guardrail 计入延迟预算。
  • 缩放看 KV 水位、扩容靠预测;离线任务填在线低谷是利用率最大杠杆;cascade 降级与量化是成本主菜。

思考题 ​

  1. 为什么 auto-scaling 用 QPS 做指标会失灵?给出一个会翻车的具体场景。
  2. 前缀亲和路由与负载均衡冲突时,你的仲裁公式怎么设计?
  3. 一条请求在网关被 429 拒绝和在实例层被抢占,对用户的体验差异是什么?平台该如何取舍?
参考答案
  1. QPS 不正比于资源占用:两个 QPS 相同的负载,一个平均输出 20 token、一个 500 token,后者 KV 与 decode 资源是前者 25 倍。翻车场景:长输出负载突增(如代码生成场景),QPS 指标平稳但 KV 水位打满,实例 OOM/抢占风暴——扩容指标必须用 KV 水位/并发 token。
  2. 双指标打分:score = α·(前缀命中收益) - β·(目标实例负载超载惩罚)。工程化:限定亲和只在"负载分位 < 阈值"的实例间生效,超载的实例直接退出亲和候选——命中收益是省 prefill(可量化为 ms),负载惩罚是 P99 恶化(也是 ms),可以统一量纲加权。
  3. 429 是快速失败(用户立刻知道、可重试、无资源浪费);抢占是已付出部分生成后失败或延迟剧增(体验差且浪费已花的算力)。取舍:能早拒就早拒(准入在前),抢占只保留给"更高优先级请求确实值得"的场景,且被抢占请求要支持断点续传(KV 保活/重算)。

参考资料 ​

最近更新