4.2 编排与容灾 路由决定了"调谁",编排决定的是"调的过程中如何稳、如何活、如何可控"。在百万 QPS 规模下,任何一个供应商的抖动都会被放大成大面积故障——编排与容灾,正是为这种不确定性上的那层保险。 编排层的位置与职责 编排层夹在路由决策和业务逻辑之间,它拿到"应该调哪个模型"的结论后,负责把它真正执行出去,并在执行过程中处理一切意外:超时、限流、报错、质量不达标。 编排层的两种典型实现 中心化编排服务:独立部署,所有模型调用经它转发。优点是策略统一、易观测、易灰度;代价是多一跳延迟,且自身必须高可用(否则全站不能调模型)。 网关/Sidecar 内嵌:编排逻辑嵌在 API 网关或 sidecar 里,省去一跳。适合延迟极敏感场景,但策略分散、版本难统一。
路由决定了"调谁",编排决定的是"调的过程中如何稳、如何活、如何可控"。在百万 QPS 规模下,任何一个供应商的抖动都会被放大成大面积故障——编排与容灾,正是为这种不确定性上的那层保险。
编排层夹在路由决策和业务逻辑之间,它拿到"应该调哪个模型"的结论后,负责把它真正执行出去,并在执行过程中处理一切意外:超时、限流、报错、质量不达标。
我的建议:百万 QPS 这类规模,优先中心化编排服务,把重试、熔断、灰度、协议归一这些策略当作独立资产集中治理;只要编排服务自身做了多副本 + 无状态 + 快失败,多一跳的延迟通常可压到个位数毫秒,性价比最高。
它的核心职责可以归纳为四件:
一个判断编排层是否到位的标准:业务代码里有没有出现任何供应商专属的接口细节?如果有,说明协议归一没做干净;如果业务只认"标准模型调用"这一个抽象,说明编排层把复杂度吞掉了。这是编排层存在的根本意义。
最基础也最关键的韧性手段是"重试 + 转移"。但要注意,重试必须带约束,否则它从保护手段变成放大器:
工程上我建议设一个"总预算"而非"每跳次数":比如一次用户请求最多允许 1 次主供应商尝试 + 1 次备用转移 + 1 次兜底,总共不超过 3 次模型调用。超过就快速失败,返回降级响应(如"服务繁忙,请稍后再试"或一段缓存的历史相似回答)。这样既保住了韧性,又护住了延迟和成本,避免"为了不死而把 P99 拖到几秒"。
重试和转移能解决"偶发抖动",但解决不了"供应商持续不可用"。这时候需要熔断:当某链路的失败率超过阈值,编排层直接短路该链路一段时间,把流量强制导向健康节点,并周期性探测恢复。
熔断有三个关键参数,调不好反而添乱:
一个常见反模式是"全局单一熔断器":把供应商 A 的所有场景共用一个熔断状态,结果某个不重要的批量任务把 A 熔断了,连核心实时链路也被殃及。正确做法是按"供应商 × 场景"或至少按"供应商 × 优先级"做细粒度熔断,核心链路有独立的状态与预算。
设想供应商 A 突发 5xx,主链路失败率冲到 70%。没有熔断时,每个请求都在 A 上超时 3 秒才转 B,P99 直接崩到 3 秒以上,且 B 开始被积压流量反压;加上熔断后,A 在失败率超阈值的瞬间被短路,流量直接走 B,P99 只抖动了几十毫秒。这个对比,是熔断"值不值得做"最直观的答案。
换模型不是点个开关。新模型、新供应商、新版本,都应该走灰度:
灰度时有个细节:对照组的流量分配最好"按用户稳定哈希"而非随机,否则同一用户一会儿走新模型一会儿走老模型,体验割裂且评估失真。让一个用户在灰度期内稳定落在同一链路,评估结果才可信。
不同供应商的接口千差万别:有的用 messages 数组,有的用 prompt 字段;有的返回 choices,有的返回 outputs;错误码体系也各不相同。编排层必须做一层协议归一:
这一层抽象做好了,后面"加一个供应商""换一个模型"都只是配置变更,而不是代码改动。反过来,如果协议归一做一半——比如只归一了成功路径,错误处理各家各写——那么一旦切换供应商,bug 会集中爆发在最容易出错的异常分支上,恰好是容灾最需要的路径。
建议内部标准请求对象至少包含:模型标识、消息列表、采样参数(temperature/top_p/max_tokens)、停止符、超时、是否流式;标准响应至少包含:文本内容、finish_reason、用量(prompt/completion tokens)、延迟、供应商标识。把这些固化下来,上层所有逻辑只围绕它们写,供应商差异被彻底关在编排层里。
当规模真正到百万 QPS,单一区域也可能整体不可用(机房、云region故障)。此时需要:
预算护栏这点值得单独强调:一次供应商故障 + 熔断没生效,可能让流量全部涌向备用供应商并瞬间打满其配额,引发二次雪崩。所以"转移目标"也要带各自的配额与降级策略,不能因为"它是备用"就无限放量。容灾链路之间也要互相设限。
兜底不一定是"报错"。当所有模型链路都不可用时,返回一段缓存的历史相似回答、或一句温和的"当前服务繁忙,已为你保留上下文,稍后回复",都比冷冰冰的 500 更能留住用户。降级响应是产品体验的一部分,别把它当纯技术问题丢给前端。
编排层产生的每一个调用,都应该留下结构化日志:调了谁、耗时多少、是否重试、是否转移、最终质量分、成本。这些是可观测性的底座。没有它,故障只能靠用户投诉发现,路由和熔断参数也永远调不准。
建议至少监控四类黄金指标:成功率、P99 延迟、跨供应商转移率、单位请求成本。转移率突然升高,往往比单个供应商失败更早预示系统性风险——它说明主链路已经在悄悄不健康,只是还没到熔断阈值。
小结:路由让请求"去对的地方",编排与容灾保证"到了也能稳稳回来"。重试跨供应商、熔断防雪崩、灰度控风险、协议归一降耦合、多区域兜底、预算护栏防失控——这几件事做好了,百万 QPS 下的模型调用才真正具备生产级的韧性,而不是纸面上的"多模型架构"。