核心概念

Cordy Gateway 的构成方式——控制平面与数据平面、模型解析链、通道与路由,以及请求生命周期。

本页解释你的客户端所调用的单一入口背后的各个部件。理解它们,就能清楚配置存放在何处、一个 model 名称如何变成真实的上游调用,以及一个请求从鉴权到计费经历了什么。

两个平面

Cordy Gateway 拆分为控制平面数据平面,二者共享一套 PostgreSQL 数据库与一个 Redis 实例。

控制平面——Admin

  • 它是什么: 一个 Django 应用(带 django-unfold 管理界面)。
  • 默认端口: 8001
  • 拥有: 数据库 schema 与全部迁移。每张表——供应商、通道、模型、定价、用户、API 密钥、审计日志——都在此定义和演进。
  • 用于: 注册供应商与通道、定义公开模型与定价、管理用户、签发与吊销 API 密钥、查看用量与审计记录。

运维人员与控制平面交互;客户端从不。

数据平面——Gateway

  • 它是什么: 一个由 Granian ASGI 服务器承载的 Starlette 应用。它就是你客户端调用的、兼容 OpenAI 的 API。
  • 默认端口: 8002
  • 数据访问: 通过连接池以原生 psycopg 访问 PostgreSQL,请求路径上没有 Django。这让热路径保持精简、快速。
  • 用于: 鉴权、作用域与配额校验、速率与并发限制、模型路由、故障转移、调用上游供应商,以及结算用量。

数据平面把 schema 视为以读为主的配置,读取控制平面写入的供应商、通道、模型、密钥与定价。

共享状态

  • PostgreSQL 保存持久化配置与记录。schema 由 Admin 迁移拥有;Gateway 读取它。
  • Redis 保存快速、临时、集群共享的状态:速率限制计数、配额预留、响应缓存、幂等键、通道冷却状态,以及把用量批量写回 Postgres 的写缓冲。与资金相关的键(已累计费用、用量缓冲)永不被驱逐。

因为 Redis 是共享的,运行多个网关副本是安全的:速率限制、配额、冷却与幂等全都是集群级的。扩展见部署

模型解析链

当客户端发送 "model": "gpt-4o-mini" 时,这个名称是一个公开模型 slug——由你选择的稳定标识。网关通过一条记录链,把它解析为具体的上游调用:

PublicModel  ──<  ProviderModel  ──<  ChannelProviderModel  >──  Channel  >──  Provider
 (公开 slug)       (厂商模型名        (在某通道上启用          (路由目标      (上游厂商)
                    + 定价)            某模型)                 + 凭据)
  • PublicModel(公开模型)——客户端请求的公开身份(例如 gpt-4o-mini)。客户端只看到这些 slug;从不看到厂商模型名或上游密钥。
  • ProviderModel(供应商模型)——把一个 PublicModel 映射到某个 Provider 的真实模型名(例如厂商字符串 gpt-4o-mini),并携带定价(input_priceoutput_price)与能力标志(supports_chatsupports_embeddingssupports_streamingcontext_window)。
  • Provider(供应商)——上游厂商集成(OpenAI、Anthropic、Azure、Bedrock 等),带 provider_type 与状态。
  • Channel(通道)——某 Provider 上的一个具体路由目标:一份上游凭据(以 Fernet 加密存储)、一个可选 base_url,以及诸如 weightpriorityregionrate_limitconcurrent_limittimeout_seconds 与可选 cost_weight 等路由属性。
  • ChannelProviderModel(通道-供应商模型绑定)——表示"此通道可服务此供应商模型"的绑定。一个通道只路由到一个供应商,且所绑定的供应商模型必须属于同一个供应商。

一个公开模型可由多个通道提供服务——同一供应商内或跨不同供应商——这正是加权均衡与故障转移得以实现的基础。

通道与路由

一个通道是抵达某模型的一条途径。由于单个公开模型可映射到多个通道,网关必须为每个请求择一,并在失败时回退。

选择通道

网关先筛选出能服务所请求模型的、健康的、符合等级的、处于活跃状态的通道,再依据路由策略择一:

策略行为
weighted先按优先级排序,再在最高优先级带内加权随机。默认策略。
cheapest有效价格最低者优先,使用各通道的 cost_weight 乘子作用于供应商模型价格。
fastest观测 P95 时延最低者优先,取自进程内时延记录器;尚无数据时回退到 weighted。
region_aware优先选择区域与调用方区域匹配的通道,再在最优分桶内加权。

默认策略由 GATEWAY_DEFAULT_ROUTING_STRATEGY 设置(默认 weighted)。客户端可用 X-Routing-Strategy 请求头按请求覆盖。见供应商客户端集成

故障转移、冷却与熔断器

  • 故障转移: 若所选通道以可重试错误失败,网关会为同一模型尝试下一个符合条件的通道。故障转移次数在 X-Failover-Count 响应头中报告。
  • 同通道重试: 瞬时错误会在同一通道上以指数退避重试,之后才启动故障转移。
  • 冷却: 反复出错(或被上游限流)的通道可被置入冷却窗口,期间被跳过。冷却状态存于 Redis,跨副本共享。
  • 熔断器: 每个 worker 跟踪供应商健康,对失败的供应商触发熔断,快速卸载负载。熔断器状态在指标中暴露。

请求生命周期

每个请求在抵达路由处理器之前,会流经一条有序的中间件链,随后进入路由与结算。各阶段依序为:

  1. 请求体大小守卫——超过 GATEWAY_MAX_BODY_BYTES(默认 10 MiB)的请求在任何缓冲之前即以 413 拒绝。
  2. 鉴权——从 Authorization: BearerX-API-Key 提取 wnx_ 密钥,以 SHA-256 哈希后查找(Redis 缓存、Postgres 后端)。无效、已吊销、未激活或已过期的密钥返回 401。若鉴权基础设施本身不可用,网关返回带 Retry-After503(这是瞬时信号,而非凭据错误信号)。
  3. 作用域与配额——路径被映射到所需作用域(chatcompletionsembeddingsmodelsbalanceadmin)。缺少该作用域的密钥返回 403 scope_denied。超出令牌配额的密钥返回 429 quota_exceeded。一份配额预留会被置入 Redis 以放行该请求。
  4. 模型权限——按用户的模型访问规则被强制执行,因此可将某密钥限制在公开模型的子集内。
  5. 速率限制——每密钥每分钟请求数限制在 Redis 中强制执行;超限请求返回 429
  6. 在途并发限制——每密钥并发请求上限为 GATEWAY_MAX_INFLIGHT_PER_KEY(默认 50);该槽位在整个流式生命周期内被占用,完成或客户端断开时释放。
  7. 护栏——可选的入站 PII 模式扫描(默认仅记录)。
  8. 区域推导——推导调用方区域(优先采用显式的 X-Region 请求头),以供区域感知路由使用。
  9. 幂等——带 Idempotency-Key 的 POST 受重放保护:TTL 内的重复请求返回已存响应,而不再次调用上游。
  10. 路由与故障转移——网关为该模型选择一个通道并调用上游供应商(经 LiteLLM 或直连的兼容 OpenAI 路径),按需跨通道故障转移。
  11. 计费与用量结算——计算令牌用量与成本,结算配额预留,扣减预付信用,写入用量记录。结算经 Redis 缓冲,由后台 worker 落盘至 Postgres。

成功响应会携带诸如 X-Channel-IdX-ProviderX-Failover-CountX-Routing-Overhead-Ms 等可观测性请求头。

各要素归属

关注点归属
供应商、通道、模型、定价控制平面(Admin),存于 Postgres
用户、API 密钥、作用域、配额控制平面(Admin),存于 Postgres
审计日志与 RBAC控制平面(Admin)
请求路由、鉴权强制、计量数据平面(Gateway)
速率限制、配额、缓存、冷却、幂等Redis(共享)
上游凭据(静态加密)Postgres 中的通道记录

后续步骤

  • 供应商——配置供应商、通道与路由。
  • API 参考——本生命周期产生的接口、作用域与错误。
  • 安全——密钥、凭据与审计记录如何被保护。