# 大模型应用怎么稳定上线?网关、限流、监控、灰度与回滚
上一篇《大模型服务怎么压测?TTFT、TPOT、吞吐与Goodput》讲了怎么用真实负载找到容量拐点。
但压测通过,只能证明这套配置在测试窗口里扛得住。真正上线后,还会遇到租户突发流量、上游超时、供应商限流、模型版本漂移、Prompt改坏、工具误调用和单副本故障。
面试官问:“你们的大模型应用怎么保证稳定上线?”
很多录友会回答:“前面加网关和限流,服务挂了就重试,再接Prometheus监控,发布时做灰度。”
这些词方向没错,但还没有形成系统:
- 限什么,是请求数、Token数,还是在途请求?
- 超时后,客户端断了,GPU上的生成任务有没有真的取消?
- 重试会不会把已经过载的下游再打一次?
- 监控报警后,凭什么决定继续放量还是回滚?
- 回滚的是模型,还是Prompt、检索索引和工具Schema这一整套版本?
稳定性不是组件装得多,而是系统能发现故障、限制影响范围,并恢复到已知稳定状态。
# 简要回答
- 网关先完成身份、租户、配额、请求大小和模型路由校验,不合格流量不要进入昂贵的推理队列;
- 限流同时约束请求速率、Token预算和在途并发,容量不足时明确拒绝或降级,不能用无限排队假装系统还活着;
- 给整条链路传播Deadline和取消信号,重试只覆盖短暂、幂等、尚未产生副作用的失败,并配合退避、抖动、熔断和备用路径;
- 用统一Request ID串起网关、RAG、模型和工具Trace,同时监控延迟、错误、成本、质量与安全指标;
- 新版本绑定模型、Prompt、索引和配置,先离线回归,再小流量灰度;一旦越过门槛,停止放量并自动回滚到上一稳定版本。
一句话:入口挡住过载,执行中切断故障,观测提供证据,灰度和回滚完成恢复。
# 详细回答
# 网关到底应该挡住什么?
LLM网关不是简单转发一次HTTP请求。它是所有昂贵计算之前的准入控制点。
至少要做五件事:
| 控制项 | 解决的问题 |
|---|---|
| 身份与租户 | 谁在调用,数据、日志和额度属于谁 |
| 权限与模型路由 | 这个调用方能否使用指定模型、工具和知识库 |
| 配额与预算 | 每分钟、每天和每个任务最多消耗多少Token或金额 |
| 请求校验 | 上下文、文件、图片和输出上限是否超出边界 |
| 统一审计 | 谁在什么时间调用了什么版本,结果和副作用是什么 |
这里有一个很实际的顺序:能在网关拒绝的请求,就不要送进推理队列。
比如用户已经耗尽日配额,或者请求声明的最大输出远超业务上限。等它占住KV Cache再终止,费用和容量已经浪费了。
多租户系统还要避免“一个大客户拖慢所有人”。配额、并发池和队列最好按租户或业务等级隔离。全局只设一个限流器,热点租户仍然可以吃光共享容量。
# 为什么只按QPS限流不够?
普通接口里,一次请求的成本通常比较接近。大模型请求不是。
一个输入200 Token、输出50 Token的分类请求,和一个输入5万 Token、输出4000 Token的长文档任务,都只算1 QPS,但它们占用Prefill、Decode时间和KV Cache的量级完全不同。
因此限流至少看三层:
- 请求速率:防止短时间大量连接打进来;
- Token预算:按估算输入、最大输出和实际消耗控制成本;
- 在途并发:限制正在排队或生成的任务数量,保护内存、连接和下游工具。
Token预估不是绝对准确,尤其在多模态和不同Tokenizer下。但它仍然比只数请求更接近真实工作量。完成后再用实际Token做账单校正。
超过容量时,系统只有三种诚实选择:拒绝、降级或排队。
排队必须有长度和等待上限。队列持续增长时,新请求即使最终成功,也可能早已违反SLO。此时返回明确的过载错误,通常比让用户等到超时更可控。
这就是背压:下游处理不过来时,压力要向上游传回去,而不是把请求藏在越来越长的队列里。

图里大小不同的行李对应工作量不同的请求。入口先按Token估算工作量,队列满了就拒绝,已经超时的任务及时取消,后面的模型服务才不会被无效请求拖垮。
# 超时、取消和重试为什么必须一起设计?
只在最外层设置30秒超时,会制造一种假象:客户端已经收到超时,但网关、模型服务和工具还在后台继续执行。
对流式生成尤其危险。用户关闭页面后,如果取消信号没有传播到推理引擎,这条请求仍会占用Decode槽位和KV Cache。
更合理的做法是传播统一Deadline:
端到端预算
= 网关处理 + 排队 + RAG/工具 + 模型首Token + 持续生成 + 网络余量
2
每一层拿到的是“还剩多少时间”,而不是各自重新计时30秒。上游取消时,下游也要尽快释放资源。
重试更不能默认打开。
适合重试的是连接重置、短暂限流和临时不可用,而且操作必须幂等。已经开始向用户流式输出、已经调用付款或写库工具、已经消耗大量Token的请求,盲目重试可能造成重复副作用和双倍成本。
生产里通常同时限制:
- 最大尝试次数和总重试预算;
- 指数退避与随机抖动,避免所有实例同时重试;
- 只对明确可恢复的错误码重试;
- 熔断持续失败的模型或供应商,避免故障扩散;
- 备用模型、模板回复或异步任务作为降级路径。
重试是放大器。 下游只是偶发抖动时,它提高成功率;下游已经过载时,它会把一次请求放大成多次请求。
# 监控为什么不能只有GPU利用率和接口错误率?
大模型应用的故障经常跨越多层:网关正常返回200,模型也生成了文本,但RAG召回了旧文档,或者工具参数错了,业务仍然失败。
所以监控要拆成四类证据:
| 维度 | 重点指标 |
|---|---|
| 流量与容量 | RPS、输入/输出Token、在途请求、队列长度、限流与拒绝率 |
| 延迟与可靠性 | TTFT、TPOT、端到端P95/P99、超时、取消、各层错误码 |
| 资源与成本 | GPU/显存、KV Cache、缓存命中、每请求Token与成功任务成本 |
| 质量与安全 | 任务成功率、Schema通过率、检索命中、工具正确率、拒答与安全命中 |
指标告诉你“哪里变差了”,日志提供具体上下文,Trace负责回答“时间和错误沿哪条链路传播”。
每个请求应有统一的Request ID,并在Trace里拆出网关、检索、重排、模型、工具和后处理Span。这样TTFT升高时,才能分清是网关排队、向量库变慢,还是模型Prefill真的变慢。
日志里不要直接保存完整Prompt、私有文档和模型输出。应按数据等级做脱敏、采样、访问控制和保留期限。可观测性是为了定位问题,不是顺手再建一份敏感数据仓库。
告警也要尽量基于用户结果。GPU利用率90%不一定是故障;P99、错误率和任务成功率同时恶化,才是用户正在受影响的证据。
# 自动扩缩容为什么不能只看CPU或GPU利用率?
推理实例从启动到加载权重、预热Kernel和接收流量,往往不是瞬间完成。等GPU打满才扩容,新副本还没就绪,队列可能已经失控。
更实用的触发信号是组合判断:
- 在途请求和队列等待持续上升;
- TTFT或P95接近SLO预算;
- Token到达率超过当前副本的已验证容量;
- KV Cache或显存逼近安全水位;
- 单副本故障后,剩余容量是否仍能接住流量。
扩容要留预热和故障冗余,缩容则要先停止接新请求,再排空正在生成的流。直接杀掉实例,会把一次正常缩容变成一批流式中断。
如果调用的是外部云API,自己扩应用副本也不一定有用。供应商账号配额、区域容量和模型限流仍可能是共同瓶颈,网关必须知道这条上限。
# 灰度发布到底在灰度什么?
大模型应用的版本,不只是一个模型名。
一次发布可能同时改变:
模型与Tokenizer
+ System Prompt和Few-shot
+ RAG切片、Embedding、Rerank与索引版本
+ 工具Schema、权限和工作流
+ 采样参数、路由和安全策略
2
3
4
5
只记录model=v2,出问题时根本回不到原来的行为。应该把这套依赖绑定成不可变发布版本,并记录配置指纹。

图里稳定主线承接大部分真实流量,只有少量请求进入试跑支线。监控门槛一旦越界,道岔立即把后续流量切回稳定版,这才是灰度发布和回滚真正的配合关系。
上线顺序可以这样走:
- 用固定Golden Set做离线质量、安全和兼容回归;
- 影子流量只复制请求、比较结果,不把新版本结果返回给用户;
- 按租户或用户稳定分桶,从小流量开始灰度,避免同一会话来回切版本;
- 每一档都观察完整业务周期,同时比较质量、延迟、错误率和成本;
- 指标稳定才继续放量,越过停止线就冻结发布或回滚。
影子流量会额外消耗Token,也可能触发有副作用的工具。复制时要关闭写操作,或者只回放脱敏、可安全重放的请求。

这张图回答的是:稳定上线为什么是一条控制闭环。网关和执行边界先缩小故障面,监控把真实流量变成发布证据;证据过线才逐级放量,一旦越界就切回上一稳定版本,避免坏版本继续扩散。
# 什么条件下应该自动回滚?
回滚条件必须在发布前写好,不能等线上报警后临时争论。
可以同时设置三类门槛:
- 硬故障:错误率、超时、P99、资源耗尽明显越界,立即回滚;
- 业务退化:任务成功率、采用率、工具正确率或安全指标显著变差,停止放量并评估;
- 成本异常:输出长度、重试次数或单个成功任务成本突然上升,先冻结发布再定位。
阈值要带最小样本量和持续窗口。只出现一个慢请求就回滚,会让发布系统不断抖动;等一小时平均值确认,又可能放大影响范围。
回滚本身也要演练。
上一稳定版本的镜像、权重、Prompt和索引必须仍然可用;数据库字段、向量索引和工具协议要向后兼容。否则代码回去了,旧版本却读不懂新数据,这不叫回滚,只是又制造了一个故障。
熔断和回滚也不是一回事:熔断是暂时切断坏下游,控制当前故障;回滚是撤销本次变更,恢复已知版本。两者经常一起用,但处理的时间尺度不同。
# 上线前最后应该验证什么?
别再看一遍功能页面就点发布。至少跑通下面这条故障路径:
突发流量进入
→ 网关按租户与Token限制准入
→ 队列到上限后背压或降级
→ 超时和取消释放下游资源
→ Trace定位到具体版本和环节
→ 灰度指标触发停止线
→ 流量切回上一稳定版本
→ 队列、SLO和质量指标恢复
2
3
4
5
6
7
8
还要做一次演练:主动让一个模型实例失败、让一个外部供应商持续返回限流、让新Prompt在回归集上退化。只有告警真的触发、影响真的被隔离、版本真的能回去,方案才算闭环。
# 知识拓展
Q1:返回429和让请求排队,怎么选?
能在等待上限内完成,并且队列不会持续增长,可以排队。预计等待已经超过SLO,就应拒绝、降级或转异步。无限排队只是把过载错误变成更晚的超时。
Q2:有多家模型供应商,失败时直接切备用模型可以吗?
可以做降级,但不能把它当成无损切换。模型的Tokenizer、上下文、工具调用、结构化输出和安全行为都可能不同。备用模型也要提前跑回归集、做容量预留,并明确哪些任务允许降级。
Q3:流式请求已经返回一半,失败后怎么重试?
通常不能对用户透明地从头重试,否则会出现重复文本和状态不一致。可以终止当前流并提示继续生成,或者从应用保存的检查点恢复。涉及工具副作用时,还要用幂等键和状态机判断是否允许继续。
Q4:质量指标反馈慢,怎么做灰度?
先用错误率、延迟和Schema通过率等快指标守住硬底线,再用抽样人工评测、LLM-as-Judge和真实业务结果补慢指标。快指标正常不等于质量正常,所以高风险版本不能因为十分钟没报错就全量。
Q5:面试里怎么回答“怎么保证稳定性”?
不要背组件名。按“准入—执行—观测—发布—恢复”讲:入口如何按租户和Token限流,Deadline和取消怎么传播,什么Trace与SLO能定位故障,灰度看哪些门槛,触发后怎样切回完整的上一版本。
压测通过,只是拿到了上线资格。
真正的生产能力,是坏请求进不来、坏故障扩不大、坏版本退得回去。
评论
验证登录状态...