
这两年只要做 AI 应用的后端十有八九会碰到同一个场景业务那边要接的模型越来越多今天一个多模态理解明天一个开源推理后天又试了几个向量化和语音合成团队还没反应过来代码仓库里已经堆了几十套完全不一样的请求结构和返回结构每个人手里都攥着不同厂商的密钥拿着各自的文档在自己那条业务线里对接。我上一份工作正好负责把 200 个 AI 模型统一收敛到一个 API 网关后面这篇文章就把当时的架构思路、落地过程和这几年攒下来的坑完整梳理一遍。这个内容不挑技术栈适合正在做 AI 平台、后端服务或者中间件架构的开发者参考也适合那些刚开始接入大模型、被碎片化接口搞到头大的团队拿来当路线图。先说结论统一 API 网关不是把请求转一转那么简单它要同时解决协议收敛、密钥治理、动态路由、成本计量、限流熔断、灰度发布和可观测性这七件事。200 个模型听起来是数字问题实际上它的复杂度是指数级的因为每个模型都有独立的协议、独立的限流规则、独立的定价逻辑和独立的故障表现如果全靠业务代码去适配总有一天会把整个系统拖垮。1. 为什么 200 个模型会逼出一个独立网关层1.1 模型接入不只是“配一个 Key”的事很多团队最开始都觉得接 AI 模型很简单充个值、拿个 Key、按照文档调一下 HTTP 接口就完事了。这个观点在两三个模型的时候勉强成立但等到模型数量上到两位数你会发现每次接入都是一次完整的小型开发要研究文档、要适配协议、要处理鉴权方式差异、要写失败重试、要统计 token 消耗、要记录日志、还要解决上游超时的问题。这些工作如果散落在每条业务线里每个业务团队都会重复做一遍而且做得五花八门。我见过最典型的情况是某个业务团队对接了六个模型代码里出现了六份基本一样但细节各异的 HTTP 客户端。有的把超时设成 30 秒有的设成 300 秒有的重试了三次有的重试了一次有的在返回里读某个字段有的读另一个字段。上线之后一遇到上游抖动每个团队都在处理同一个问题但是没有人知道全局到底发生了什么。当我们开始规划 200 模型接入的时候就形成了一条明确判断这条链路必须抽出来单独做成基础设施不能继续留在业务层。只有把它变成一层独立网关才能让新模型接入从“每个业务做一次适配”变成“平台做一次适配、所有人直接可用”。1.2 四个失控点协议、密钥、账单、故障我习惯把多模型接入带来的问题分成四类这也是网关架构设计的基本出发点。第一是协议碎片化。不同厂商的接口风格差异非常大有的走流式、有的非要轮询有的参数是嵌套 JSON、有的参数是扁平数组有的返回的是标准事件流、有的直接在一个字段里返回完整结果。业务侧如果直接面对这些差异每次切换模型都要动业务代码。第二是密钥分散。每个模型一个 Key每个 Key 有独立的配额和计费方式。密钥如果散落在各个服务环境变量、配置文件甚至前端代码里安全风险极高而且一旦某个同学离职或者泄露 Key根本不知道影响面有多大。第三是账单无底洞。没有统一网关之前每月的模型费用只能看厂商后台根本分不清是哪个业务线花的钱、哪个模型烧得最多、哪个调用行为是最浪费的。成本分析做不了预算控制就更谈不上。第四是故障各自为战。模型上游服务经常不稳定有的模型在高峰期会大量超时有的会突然限流还有一些返回的内容格式偶尔会坏掉。没有统一网关故障就会直接打到业务层业务代码被迫写一堆防御逻辑。1.3 为什么不能用“业务里写适配器”解决有同学会问直接用适配器模式写一个抽象层不行吗为什么非要单独搞网关适配器模式在小规模下完全没问题但是它有几个天生的短板。第一是抄袭成本高。每个业务服务都要集成这套适配逻辑语言不一样还得各写一份。我们当时有微服务有脚本任务还有数据分析平台每个技术栈都搞一遍适配器光维护就是一个灾难。第二是横切能力缺失。限流、熔断、密钥管理、费用计量这些能力和具体业务无关但适配器被业务代码持有就很难统一实现只能每个服务各自为政。第三是升级代价大。模型协议一变所有集成方都要跟着整改排期经常要对齐很久。网关的核心价值在于把这些问题全部收敛到一个“横切面”上业务侧只面对一个稳定接口协议、密钥、路由、计量都在网关里统一处理。2. 整体架构设计控制面和数据面分离2.1 网关分层接入层、路由层、模型适配层不少第一次做网关的同学容易把所有逻辑塞在一个服务里这个服务既要做 HTTP 接入又要做模型适配还要做后台管理和数据统计。起步阶段看着省事流量一上来就会遇到性能瓶颈而且任何改动都可能影响到线上流量。我当时把网关从逻辑上拆成两层数据面和控制面。数据面是真正处理请求的代理层它对性能要求最高只做最核心的事接收请求、做认证、转发、流式透传、限流、粗略计费。这一层要尽量快不能在里面跑复杂的后台逻辑。控制面负责模型台账、密钥管理、配置下发、计量汇聚、告警和后台界面。它的吞吐量要求不高但是逻辑非常复杂而且需要频繁变更。把这两层拆开以后数据面可以做水平扩容控制面可以独立迭代互相不受影响。实际部署的时候数据面通常是一组无状态实例可以随时加机器控制面是一个独立的服务连数据库和配置中心。整个链路看起来是这样客户端请求先打到接入网关接入网关完成认证和基础限流然后交给路由引擎路由引擎根据模型路由规则选出一个目标上游再由模型适配层把请求转换成目标模型的原生格式完成转发后把响应按统一协议返回给调用方。2.2 为什么业务侧只认一个“标准模型协议”200 多个模型不可能暴露 200 多套对外接口那和没有网关就没有区别。我们的做法是定义一套内部的“标准模型协议”。这个标准协议参考了市面上大多数模型接口的习惯和约定统一用 JSON 格式接收消息列表统一用标准事件流返回流式结果输出内容里带清晰的元信息包括模型名、用量、延迟、缓存命中状态等。业务侧不管最终调的是哪个模型拿到的返回结构永远是同一套。这样做有非常现实的好处。业务侧接到一个新模型需求时可能只需要改一行配置代码完全不用动。就算底层模型换了对业务侧也是透明的。标准协议本身变成了一种内部契约把业务侧和底层模型生态彻底解耦。2.3 模型台账所有模型信息先结构化200 模型的配置不可能散落在代码里我们把每个模型的信息抽象成一个“模型定义”包含名称、所属厂商类型、协议格式、接入地址、鉴权方式、支持的参数、上下文窗口、计费单价、限流阈值、超时配置、健康状态等几十个字段全部存到控制面的数据库里。新增一个模型时运营同学只需要在后台填一张表单提交后配置自动推送到数据面。整个过程不需要发版不需要重启新模型立刻可以被业务侧使用。这个模型台账是整个系统的“字典”也是后面做自动化路由、成本核算、故障处理的数据基础。这里有个容易忽略的细节模型定义一定要包含“上下文窗口”和“单请求最大 Token”这些元数据否则后面做 Token 计费和控制时无从下手。3. 核心功能拆解一个请求从进网关到返回业务侧的经历3.1 协议转换把“方言”翻译成“普通话”模型协议转换是最容易低估工作量的一环。不同模型协议的差异不只是在字段名上而是在消息结构、流式格式、错误码、参数类型、长度单位各个方面。举个例子有些模型把对话历史放在一个messages数组里数组里的每条消息带role和content有些模型却要求把历史拼成一个长字符串放在prompt字段里。有的模型支持max_tokens控制长度有的模型要叫max_new_tokens还有一些模型用temperature控制随机性但取值范围完全不同。甚至有的接语音和视觉的模型输入要求 base64 编码的图像数据和纯文本接口毫无共同点。我们的做法是给每个模型类型编写一个独立的“适配器组件”负责把标准协议翻译成目标模型原生协议。翻译过程在网关内部完成业务层无感。翻译之后还需要处理返回内容把上游的非标准格式再翻译回标准协议包括错误信息也要做一层统一化。这里有一个我在项目里总结的比较实用的经验错误码一定要先统一再透传。上游返回的错误五花八门有 429 限流、有 5xx 超时、有参数校验错误如果不统一业务侧就得解析每家厂商的错误结构。我们把所有上游错误映射到几大类标准错误码业务侧看到的是一个稳定、可预期的语义化错误。3.2 路由核心不只按模型名转发网关的路由能力很多人理解得比较浅以为就是根据请求里的模型名找到对应上游地址。实际上我们在 200 模型场景里动态路由是保证稳定性最重要的手段之一。我们实现了三类路由策略。第一类是最基础的“精确路由”请求里明确指定模型名网关直接转发到目标模型。这种最简单也最常用。第二类是“优先级路由”同一个逻辑模型背后可以配置多个实际模型作为备用当主模型故障或限流时自动切换到备用模型。比如主模型超时超过阈值网关会把这次请求转发到备用模型业务无感。第三类是“语义路由”请求不指定具体模型只携带任务类型和上下文特征网关根据模型的能力标签、当前负载、历史成功率来动态选择一个最合适的模型。这个在企业内部比较有用比如“摘要任务”可以自动选用成本更低的模型“复杂推理”自动选用能力更强的模型。路由决策必须在转发前就完成一旦开转就不能再变。我们通过权重、健康状态、实时错误率和人工运维指令共同决定路由结果。每一次路由决策都会记录到日志里方便事后复盘为什么某个请求走了某个模型。3.3 密钥治理虚拟 Key 和多租户隔离密钥问题是多模型平台绕不开的坎。业务侧如果直接使用每个上游模型的 Secret Key一是暴露面太大二是无法精细控制权限。我们的做法是网关自己维护一套“虚拟 Key”体系业务侧调用网关时只出示网关下发的虚拟 Key网关通过解析虚拟 Key 得到对应的租户、模型范围、速率限制和可用额度再决定使用哪个上游密钥完成转发。虚拟 Key 的价值在于可以独立吊销。某个员工离职了或者某条业务线出现异常调用管理员在后台一键禁用该虚拟 Key不必去所有上游厂商那边重置密钥。虚拟 Key 还可以绑定模型白名单一个 Key 只能调用指定的几个模型进一步缩小滥用面。密钥在网关里必须加密存储日志里要强制脱敏。我们当时还专门写了一个日志过滤器把请求日志里出现过的 Key 统一替换成打码形式否则排障时一翻日志就是一地密钥。另外一个关键点是上游密钥的刷新机制很多厂商的 Key 有有效期或者额度限制控制面需要提前检查密钥健康度快到期前提醒运维换新。3.4 流式响应转发边转发边记账边容错对话类模型绝大多数走的是流式响应也就是 SSE 风格。网关对流式的处理直接决定了用户感知的“首字延迟”和“流畅度”。流式转发看起来就是“上游吐一段、网关转发一段”实际上有很多细节。第一个问题是协议转换不同模型的流式数据格式差别很大有的直接吐data:前缀的内容有的要拼接, 有的中间还夹杂注释行网关必须把上游的流一段段解析翻译成标准协议后再转发给调用方。第二个问题是记账。流式响应里 token 是逐步到达的但计费必须在请求结束时精确结算。我们采用“边转发边统计”的方式在网关转发每个数据块时同时累计输入 token 和输出 token 的估算值等流结束后再做一次修正把真实用量写入计量系统。这要求流式转发模块和计量模块必须配合得足够紧密不能各做各的。第三个问题是上游中断。流式连接随时可能被上游断掉这时候网关必须立刻向调用方返回一个“流中断”事件而不是让客户端傻等。我们专门设计了一套流结束事件语义正常结束、异常中断和被限流都要区分清楚。否则客户端那边会因为拿不到终止标记而发生卡死。做流式转发时还要额外注意压缩传输。很多厂商返回的数据块如果开启 gzip网关转发时如果直接透传客户端解析会非常困难。我们统一选择在网关层解压、再按照标准协议重新压缩或直接明文输出这样对整个调用链路更可控。4. 稳定性和成本控制网关也是“钱袋子”和“安全阀”4.1 限流与并发控制别让一个调用方拖垮整个网关接 200 多个模型最怕的就是某个调用方发疯一样跑任务把网关的线程池打满导致其他正常请求全部排队。所以我们把限流做成了多维度。维度一是按租户限流每个业务线有独立的每秒请求数上限和并发数上限。维度二是按模型限流每个模型有全局的调用配额超过后直接拒绝或者排队。维度三是按上游实例限流防止某一个上游模型因为热度冲高被打挂。限流不能只做一个全局计数器网关是分布式部署的我们使用了一个轻量的分布式限流组件每个实例先按比例分配配额再通过中心节点动态协调。限流触发时返回的也是统一标准错误码客户端可以据此做重退避。并发控制是比限流更细的一层。有些视觉模型单次请求非常耗时如果一次性进来几百个并发请求上游基本必挂。我们在网关层给每个上游模型维护一个“正在处理中的请求数”超过阈值就直接排队或快速失败避免把上游压垮。4.2 熔断与自动降级上游不可用不等于整个功能不可用模型上游的事故我们都见过不少有的厂商大面积超时有的模型一天崩好几次。网关必须在这些情况下保住业务方的体验。熔断器的设计我们参考了常规微服务的思路但针对 AI 模型做了一些改动。每个模型上游维护一个动态错误率指标当连续失败达到阈值时熔断打开后续请求不再进入该上游而是走降级策略。降级策略有三种直接失败并返回错误提示自动重试备用模型降级到缓存结果。具体用哪种看业务场景的容忍度。比较难处理的是部分模型会间歇性失败一会儿好一会儿坏如果熔断恢复太频繁上游会被反复试探搞得不稳定。我们最后采用了“半开探测”机制熔断打开后每隔一段时间放几个探测请求进去如果探测成功就恢复流量失败就继续熔断。这套机制上线后上游大面积抖动时网关侧的可用性从 92% 提升到了 99% 以上。需要提醒的是自动降级到备用模型时一定要在响应里带上实际使用的模型标识。否则业务方看着结果正常实际上模型已经换了如果后续发现效果不一致连排查入口都没有。4.3 Token 计费网关最复杂的业务逻辑成本控制是统一网关最敏感、也最复杂的一块。我们每个月要通过网关给各个业务线和各个模型出一份账单误差不能太大。Token 计算有两个难点。第一是不同模型的 token 切分规则不一样有的按字符有的按子词有的还会为特殊字符多算 token同一个文本在不同模型下算出来的 token 数可能差 20% 以上。第二是流式响应下输出 token 要实时统计, 但上游不一定每次都把真实 token 数告诉网关。我们的方案是“估算 实测校准”。请求开始时根据输入文本做一次 token 预估算用于限流和成本预检响应结束时优先读取上游返回的用量字段真实 token 数如果没有真实字段再用本地 tokenizer 对转发内容做最终估算。账款以最终估算为准预估算只用于事中控制。这里有个容易被坑的点很多模型接口虽然返回了usage字段但流式模式下这个字段只出现在最后一个数据块里如果网关没有正确解析最后一个块用量就会丢。我们专门为每个模型适配器实现了“流结束事件解析”确保 usage 被完整捕获。账单粒度我们是按“租户 模型 时间窗口”三个维度聚合的。每次调用产生一条计量记录控制面异步聚合成小时级和天级报表并设置预算预警。哪条业务线本月已经烧掉了 80% 预算系统自动通知相关负责人避免月底对账时才傻眼。4.4 语义缓存高频请求没必要每次都花真金白银AI 模型调用频次上来之后很多成本是可以省掉的。最简单的就是请求去重尤其是报告中那种重复性极高的查询场景同一个问题频繁被问到每次都调模型就是烧钱。我们在网关层做了一个“语义缓存”。普通缓存按请求文本精确匹配效果有限因为用户表述可能略有差异但语义一样。语义缓存先把请求文本向量化用向量检索去找语义相近的历史缓存结果。相似度超过阈值就直接返回缓存不再调用上游模型。做语义缓存有几个前提条件需要想清楚。第一是隐私边界缓存里不能存敏感数据我们对所有请求文本做了脱敏和白名单控制。第二是时效性有些模型返回的内容可能过时缓存必须有过期时间和主动失效机制。第三是收益度量当时实测在通用问答类场景里语义缓存命中率能做到 15% 左右对降低成本和延迟都有明显帮助但并非所有场景都适用。4.5 灰度发布与模型替换新模型上线不用提心吊胆每次有新模型接入时我们都不敢直接把所有流量切过去哪怕它宣称效果更好。灰度发布机制就变得非常重要。网关支持在模型路由规则里配置权重比例比如新模型先放 1% 的流量观察稳定性和效果指标再逐步提升。对于效果对比型的需求我们还做了一个 A/B 对比能力同一个请求同时或轮流打到旧模型和新模型上在网关侧记录两者的响应结果、延迟和成本供评估使用。灰度发布的关键是“业务无感”。我们尽量不让业务方感知到灰度切换所有灰度参数都在控制面配置数据面自动执行。灰度过程中如果发现错误率上升一键回滚到之前的全量状态。这套机制后来成为我们引入新模型时的标准动作。5. 上线半年踩过的坑问题排查与决策记录5.1 常见故障速查表网关这类基础设施上线后故障类型不会太多但每种一出现就是全局性的。我整理了半年里碰到的高频问题做成一张速查表给团队成员排障时直接用。症状根因解决办法客户端收到不完整的流式内容网关未处理上游后半段数据块或连接被中间层截断流式转发模块增加超时检查识别非正常流中断偶发 502 但上游日志正常网关与上游之间连接池耗尽或 KeepAlive 配置不合理调大连接池优化上游空闲连接回收策略计费报表金额比厂商后台偏高流式数据块重复计数或 usage 字段被重复写入检查流结束事件处理逻辑对 usage 做幂等校验某个模型突然大量报错上游模型因为并发过高被限流返回 429为每个模型增加并发预检超过阈值时走备用模型虚拟 Key 明明有效却被拒绝多租户配置和 Key 的模型白名单冲突后台增加 Key 联动校验修改模型定义时自动检查存量 Key日志里出现完整密钥明文日志过滤器生效前已经打印了完整请求体请求体脱敏改为必选插件并做人工扫描清理历史日志5.2 排查链路每个调用都带上唯一追踪 ID200 个模型排查问题时最大的障碍是“对不上账”。一个请求从客户端到网关再到上游绕了多个系统如果每个系统各存各的日志出问题时很难把链路串起来。我们在第一版就引入了追踪 ID 机制客户端发起调用时网关分配一个全局唯一 ID这个 ID 一直贯穿请求生命周期带上游请求、网关日志、计量记录、后台审计日志。排查时只要拿到一个 ID就能把整个旅程读出来。追踪 ID 需要妥善处理的一个场景是异步和流式。流式请求经常持续几十秒甚至几分钟期间会产生多段日志。我们要求所有日志都携带会话 ID 和段序号按序归档否则流式日志混在一起根本看不了。排查工具里可以直接按会话 ID 拉出按时间排序的完整事件流从进入网关注册路由到上游响应首个数据块再到完整结束每一步都有时间戳。这个方法后来被直接用到了我们自己的排障流程中非常管用。5.3 配置热更新新增模型不能重启服务刚开始设计时最简单粗暴的方案是每次改配置就重启数据面服务。结果 200 个模型的管理周期非常频繁几乎天天有改动如果每次都要重启线上稳定性根本保证不了。我们最后采用了“配置版本 增量推送”的方式。控制面生成新配置时会打一个版本号然后通过内部配置通道推送到所有数据面节点数据面加载新配置后自动切换。整个过程中正在进行的请求不受影响新请求走新配置配置版本也会记录到日志里。这个过程里碰到过磁盘写满导致配置推送失败、部分节点加载到旧版本等异常情况。后来加了一个配置健康检查每次推送完成后控制面要求所有节点上报当前配置版本不一致的节点自动重新拉取。这个机制一定要做否则“部分节点配置不同”在网关场景里是最大的隐形事故源。5.4 团队协作和变更管理的一点体会最后说说团队层面的问题。网关是基础设施牵一发而动全身所有变更都要有非常明确的评审流程。我们后来形成了一套约定新增模型必须有对应的 Model Card 原型测试记录不能只看文档就上线修改路由策略前必须在预发环境压测一轮尤其是涉及自动降级时密钥轮换前必须筛选出所有正在使用该密钥的调用方逐一体检后再切换线上问题复盘时必须区分是网关自身问题、上游模型问题还是业务调用问题不能一锅端。这套约定看起来简单但执行之后系统的稳定性明显提升。因为很多事故不是因为技术做不到而是因为变更太随意。6. 写在最后的小技巧如果你也在规划类似的统一接入层我个人建议第一步不要贪多别一上来就想着把所有模型全部接完。先接两三个典型场景把数据面转发、路由、计量、虚拟密钥跑通形成一个可复用模式再逐渐铺开。还有就是能买现成的组件就不要重复造轮子但模型适配这层必须自己控制。因为这个适配层是整个平台的核心壁垒它决定了你接入新模型的速度和稳定性。把协议适配做得足够好后续每接一个模型都是纯增量工作那种感觉非常舒服。另外一个小技巧网关的监控指标一定要在第一天就设计好。除了常规的请求量、错误率、延迟之外一定要统计每个模型的首字延迟、Token 吞吐量、单次调用成本、流式中断率、缓存命中率这几个特殊指标。这些指标在你后续做容量规划、成本预算和模型选型时比任何经验值都可靠。做了大半年之后回头再看统一 API 网关这件事本质上是用一层基础设施的复杂度换取了全公司 AI 接入的自由度。它不会让单个模型跑得更快但会让整个组织在 AI 生态变化时始终保持从容。