跳到主要内容

Route(路由)

当前版本的 route 运行时数据直接来自 PostgreSQL routes 主表。

关键字段

  • id
  • tenant_id
  • name
  • path_prefix
  • disabled_at
  • disable_auth
  • protocol_transformation_type
  • legacy_bearer_auth_tokens
  • passthrough_auth_token
  • allow_missing_model_pricing
  • upstreams
  • upstream_selector
  • model_selector
  • plugin_config(运行时由 plugin_configs 表聚合得到)

注意:

  • 上面的 plugin_config 是运行时字段
  • Management API 的 Route 资源已不再包含这个字段
  • 管理面需要通过独立的 RoutePluginConfigService 管理 route 级插件配置

当前运行时语义

一条请求命中 route 后,会继续执行:

  1. path_prefix 最长前缀匹配
  2. 按 route 认证优先级决定是否鉴权
  3. 进入 route 绑定 upstream 与 selector 选择
  4. route.upstreams[] 为基础集合,再叠加 route / consumer / api key selector
  5. upstream_models 中解析候选 upstream,并按 key 展开成候选集
  6. 先按 route.upstreams[].priority 从小到大排序;仅在同优先级内按 route.upstreams[].lb_weight 做加权随机无放回排序
  7. 把候选列表交给 forwarder,在内部做 fallback 编排

补充:

  • GET /v1/models 不再透传某个上游的 /models
  • gateway 会先按现有认证 / route 绑定 / selector / 协议过滤逻辑解析“完整可用 upstream 集合”
  • 当前本地 /models 聚合不会读取 provider / upstream capabilities
  • 然后聚合这些 upstream 的 upstream_models.model,去重后按字母序返回 OpenAI 兼容的 models list
  • 因此 /v1/models 的结果不会受 route.max_attempts 重试上限影响

Forwarder Capabilities

  • forwarder capability 已从 route 移到 provider.capabilities / upstream.capabilities
  • 这组能力只描述“请求已经进入 forwarder 且已选到某个 upstream 后,是否允许继续处理该接口”
  • upstream.capabilities 非空时会完整覆盖 provider 默认值;为空时继承 provider
  • 当 provider 与 upstream 都未显式配置时,运行时会按 provider.protocol 推导默认能力集

协议转换

  • chat 入站协议按裁剪后的请求路径判断:/chat/completions/responses/messages
  • 上游协议按 upstream -> provider -> protocol 判断
  • 默认 protocol_transformation_type = if-different-protocol
  • protocol_transformation_type = disabled 时,运行时会追加一个内部 upstream selector:aidy/protocol = 入站协议,因此候选阶段只会保留同协议 upstream
  • 当前 chat 主线已固定走统一 IR 模型:
    • 按入站协议解析 RequestIR
    • 按候选 upstream 的 provider.protocol 组装请求
    • 成功候选返回后,再按原始入站协议回组装响应
    • 注:即使同协议,当前 chat 主线仍采用先解析 IR 再重组的路径; protocol_transformation_type 在这里的影响是,forced 会忽略未知的字段,而 if-different-protocol 则保留(更类似透传);但无论是哪种,如果请求体无法通过协议的校验将返回错误
  • chat 路径当前支持三种入站协议:
    • /chat/completions -> chat-completions
    • /responses -> open-responses
    • /messages -> claude-messages
  • 成功候选返回后,gateway 会始终按原始入站协议回组装响应

Chat 请求体解析

当前 chat 请求在进入 forward_chat middleware 前,会先由 gateway 解析为内部 IR。

这意味着当请求体无法通过对应入站协议的解析或校验时,gateway 会直接返回本地 400 invalid chat request body: <reason>,而不会继续透传给上游做校验。

多 Upstream 与 Fallback

  • 一个 upstream 配置多个 API key 时,会被展开成多个独立候选
  • 候选排序先按 route.upstreams[].priority 从小到大分层;仅在同优先级内再按 route.upstreams[].lb_weight 做加权随机无放回
  • 多 API key 当前只是展开成多个 id/key 凭证候选,等价于多条相同 route-upstream priority 和 lbWeight 的候选
  • route.upstreams[].priority 的语义是“数值越小优先级越高”
  • 单次请求最多尝试 route.max_attempts 个候选,默认 2
  • 任意非 2xx、transport error、assemble/parse error 都会触发 fallback
  • 对于流式 chat,请求一旦成功向客户端写出首个 event,就锁定当前候选,不再 fallback

认证优先级

当前 route 的认证优先级固定为:

  1. disable_auth = true
  2. passthrough_auth_token = true
  3. legacy_bearer_auth_tokens 非空
  4. 默认走 consumer_api_keys

Selector 语义

  • route.upstreams[] 决定这条 route 允许使用哪些 upstream
  • route.upstream_selector / consumer.upstream_selector / consumer_api_key.upstream_selector 会继续收紧 upstream 候选
  • route.model_selector / consumer.model_selector / consumer_api_key.model_selector 会继续收紧 upstream_models 候选
  • 空 selector 表示不额外限制
  • 具体语义见 Label & Selector

如果 route.upstreams[] 为空,则这条 route 当前没有任何可用 upstream。

缺失模型价格策略

  • 默认情况下,alias 映射后的真实上游模型必须存在对应 provider pricing,否则请求会在转发前被拒绝。
  • Tenant 或 Route 任意一个设置 allow_missing_model_pricing = true 时,允许缺失价格的请求继续。
  • 价格检查使用实际请求到上游的模型名;例如客户端请求 alias gpt-4o-mini-latest,映射到上游 gpt-4o-mini 后,会检查 gpt-4o-mini 的价格。