AI API 网关架构设计:如何实现多模型统一路由与自动故障转移
一个 API Key,调用 Claude、GPT、Gemini、DeepSeek 所有主流大模型。听起来简单,但背后的工程细节远不止换个 endpoint 那么简单。
为什么需要 AI API 网关
如果你的业务只用一个模型提供商,直接调用官方 API 没什么问题。但现实中大多数团队会遇到以下场景:
- 多模型并存:不同功能模块用不同模型,有的用 Claude 做代码审查,有的用 Gemini 做文档摘要,有的用 DeepSeek 跑批量任务
- 单点故障风险:OpenAI 在 2024 年多次出现 API 中断,Anthropic 也会有限流。没有 fallback 就意味着你的业务直接挂掉
- 计费混乱:每个提供商有独立账单,token 单价不同,月底对账是噩梦
- 合规与审计:企业客户要求记录所有 AI 调用,方便审计、排查问题
AI API 网关就是解决这些问题的基础设施层。它站在你的应用和各个模型提供商之间,统一入口、统一协议、统一计费、统一监控。
核心架构:四层设计
我们在设计 TheRouter 时把整个请求链路分成四层,每层职责明确:
客户端请求
│
▼
┌─────────────────────────────────┐
│ 1. 请求解析层(Ingress Layer) │ ← 协议适配、鉴权、参数校验
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ 2. 模型路由层(Router Layer) │ ← 模型映射、路由选择、健康过滤
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ 3. Provider 适配层 │ ← 协议转换、错误归一化、重试
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ 4. 计费层(Billing Layer) │ ← Token 计量、费用记录、余额扣减
└─────────────────────────────────┘
│
▼
上游 Provider(OpenAI / Anthropic / Bedrock / Vertex AI / ...)
第一层:请求解析层
所有入站请求首先到达这里。主要职责:
- 协议适配:支持 OpenAI Chat Completions 格式(
messages数组)、OpenAI Responses API(input字段)、Anthropic Messages API 等多种请求格式,统一转换为内部标准格式 - 鉴权:验证 API Key 合法性,加载租户配置(路由策略、允许使用的模型、消费上限)
- 参数校验:检查
model字段是否存在、请求体格式是否合法,在路由前快速返回错误
这一层的关键设计原则是快速失败——所有能在路由前拒绝的请求,不要带进下游。
第二层:模型路由层
这是整个网关最核心的部分。
两层模型抽象
我们设计了两层模型命名体系:
- Standard Model(标准模型):对外暴露的模型 ID,格式为
品牌/模型名,比如anthropic/claude-sonnet-4.6、openai/gpt-5、google/gemini-2.5-pro。这是客户看到的,也是/v1/models接口返回的。 - Upstream Model(上游模型):实际调用时使用的提供商内部模型 ID,比如通过 Bedrock 调用 Claude 时,上游模型是
us.anthropic.claude-sonnet-4-5-20251001-v1:0。
两层抽象的好处是:客户代码里只出现标准模型 ID,内部路由切换对外完全透明。 我们把一个 Anthropic 直连路由切换成 Bedrock 路由,客户完全无感知。
配置文件结构:
src/config/
├── standard-models.yaml ← 标准模型定义 + 售价
└── provider-models/ ← 每个 provider 一个文件
├── anthropic-api.yaml ← Anthropic 直连
├── bedrock-us-east-2.yaml ← AWS Bedrock us-east-2
├── openai-api.yaml ← OpenAI 直连
└── vertex-ai-us-central1.yaml← Google Vertex AI
每个 provider 文件里,通过 standard_model 字段把上游模型挂载到标准模型上:
# bedrock-us-east-2.yaml (示意)
upstream_models:
us.anthropic.claude-sonnet-4-5-20251001-v1:0:
standard_model: anthropic/claude-sonnet-4.6
priority: 20 # 优先级,越小越优先
cost:
input: 3.00 # $/MTok,成本价
output: 15.00
路由选择算法
路由层根据以下因素决定用哪个 provider:
- 优先级(Priority):每条路由有一个
priority值,数字越小越优先。同一个标准模型可以挂多条路由,形成有序的 fallback 链 - 能力过滤(Capability Filter):如果请求用了
tools(函数调用)或vision(图片输入),过滤掉不支持这些能力的 provider - 健康状态(Health Filter):过滤掉当前不健康的 provider(下文详述)
- 客户偏好(Customer Preference):租户可以通过请求头或 API 参数指定
only(只用某些 provider)、ignore(排除某些 provider)、order(自定义排序)
支持两种路由算法,可以按租户或按请求切换:
priority:按优先级排序,优先选最高优先级的健康路由lowest_cost:在健康路由中选当前成本最低的
第三层:Provider 适配层
每个 provider 是独立的微服务,负责:
- 协议转换:把网关内部格式翻译成 provider 原生 API 格式(Anthropic 的 Messages API、OpenAI 的 Chat Completions、Bedrock 的 InvokeModel 等)
- 错误归一化:把各家的错误码统一映射到网关内部错误类型(
error_5xx、error_4xx、timeout、rate_limit),让上层路由决策逻辑不需要感知具体 provider - 内部重试:provider 层做短暂的内部重试(只针对 transient 5xx),与路由层的跨 provider failover 分离
关键设计决策:每个上游 API 必须有独立的 provider 服务。 即使两个 provider 的 API 格式兼容(比如许多第三方都兼容 OpenAI 格式),也要给它们各自的服务。原因:provider 特有的错误处理、reasoning token 格式、Rate Limit 行为各不相同,共用镜像会埋下难以排查的 bug,也让独立升级变得困难。
第四层:计费层
每次请求完成后,计费层负责:
- Token 计量:从响应的
usage字段读取实际消耗的 input/output token 数 - 成本计算:根据实际使用的 provider 的成本价计算原始成本,按售价计算向客户收取的费用
- 记账:写入计费流水,扣减余额
计费层和路由层共享同一份定价配置——标准模型有"售价",provider 路由有"成本价"——两层价格独立维护,网关统一管理 margin。
故障转移机制
这是 AI 网关区别于普通 API 网关的核心能力之一。
Provider 健康检查
网关维护一个 provider 健康状态缓存,来源有两个:
- 主动探测:定期向各 provider 发送探测请求,根据响应时间和错误率更新状态(
healthy/degraded/unhealthy) - 被动感知:每次真实请求如果返回 5xx 或超时,记录失败事件,动态调整该 provider 的健康分数
自动 Fallback 流程
请求 → 路由层选出有序候选列表 [A, B, C]
│
▼
尝试 A
│
A 返回 503 ──→ 记录失败,标记 A 健康分下降
│
▼
尝试 B
│
B 成功 ──→ 返回响应,记录 fallback_depth=1
路由层在构建候选列表时已经过滤掉 unhealthy 的 provider,但 degraded 的仍然会保留(排在后面)。这样在所有健康 provider 都不可用时,降级 provider 还能作为最后兜底。
我们在 Prometheus 指标里专门追踪 fallback 深度(gateway_fallback_depth)和 fallback 总次数(gateway_fallback_total),用于告警和 SLA 评估。
流式响应的特殊处理
Fallback 在流式(SSE)请求下有一个关键约束:一旦响应头已经发送(HTTP 200 + Content-Type: text/event-stream),就不能再切换 provider 了。
所以流式请求的 fallback 只能在第一个 token 到达之前触发。具体做法:
- 建立 SSE 连接后,先不立即向客户端发送响应头
- 等待 provider 开始返回数据流(拿到第一个 chunk)
- 第一个 chunk 确认成功后,再向客户端发送响应头 + 开始转发数据
- 如果在第一个 chunk 到来前 provider 报错,可以切换到下一个 provider 重试
这个设计增加了首 token 延迟(TTFT),但保证了流式请求的可靠性。
另一个挑战是流式过程中断:数据已经开始传输,中途 provider 连接断掉了怎么办?这种情况我们选择向客户端发送一个特殊的错误 chunk,然后关闭连接——此时重连到新 provider 并续传是不现实的,因为我们无法知道客户端已经收到多少内容。
实践中踩过的坑
1. SSE 连接泄漏
早期版本里,如果客户端提前断开连接(比如用户刷新了页面),网关侧不会立即感知,上游的 SSE 流还在跑,消耗资源还在计费。现在我们监听客户端连接的 close 事件,客户端断开时立即 abort 上游请求。
2. 跨 Provider 的 Token 计数差异
不同 provider 对同一段文本的 token 计数略有差异(因为分词器不同)。如果用预估 token 数做余额预扣,误差会导致少扣或超扣。我们的做法是:预扣时用一个保守估算(留 20% buffer),请求完成后根据实际 usage 做精确结算。
3. Bedrock 的特殊性
AWS Bedrock 不是一个简单的 HTTP API,它需要 AWS SigV4 签名。我们把 Bedrock 做成一个独立的 provider 服务,所有签名逻辑都封装在里面,网关主体不感知 AWS SDK。
4. 响应里的模型名字必须回显标准模型 ID
Claude 官方 API 返回的响应里,model 字段会是类似 claude-sonnet-4-5-20251001 这样的内部版本号。我们必须把它替换成用户请求时用的标准模型 ID(比如 anthropic/claude-sonnet-4.6),否则客户代码里做模型判断的逻辑会出错。
架构总结
一个生产可用的 AI API 网关需要解决的问题远比"转发请求"复杂得多。上面提到的两层模型抽象、能力感知路由、流式 fallback 策略、精确 token 计费,每一块都有相当多的工程细节。
如果你正在构建自己的 AI 基础设施,建议:
- 不要直接暴露 provider 名字给业务代码——用抽象层隔离,方便未来迁移
- 从第一天就做健康检查和 fallback——AI provider 的稳定性远不如传统 SaaS
- 流式请求单独处理——SSE 的错误处理逻辑和普通请求完全不同,不能复用
- 双层定价——成本价和售价分开管理,方便调整 margin 和做成本分析
如果不想自己造轮子,TheRouter 提供了一个已经解决以上所有问题的 AI API 网关,一个 API Key 接入所有主流大模型,支持自动故障转移和统一计费。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)