Skip to content

[上游跟踪 #1730] 渠道 RPM 与并发准入控制 #38

Description

@faithleysath

上游来源

Nexus 目标

QuantumNous#1730 拆成可被上游接受的、与现有渠道选择器兼容的渠道级准入控制,并在上游提交完整 PR。目标不是直接引入现有候选 PR,而是重新实现可靠的 RPM 与并发预留。

每个渠道新增两个可选限制:

  • max_concurrency:渠道同时在途的上游请求数;0 或缺省表示不限。
  • rpm_limit:渠道每分钟允许开始的上游请求数;0 或缺省表示不限。

限制按渠道聚合,多 Key 渠道的初版语义为所有 Key 共享渠道总额度。现有优先级、权重、分组、auto group 和渠道亲和仍然有效。

必须满足的路由语义

  1. 在发送上游请求前完成原子准入和容量预留。
  2. 候选渠道达到任一上限时,从当前优先级的剩余候选中重新选择;满载跳过不消耗上游重试次数,也不记录为上游错误。
  3. 当前优先级全部满载后,才进入下一优先级或下一自动分组。
  4. 所有候选都无法准入时,直接返回稳定的本地容量错误和 Retry-After,不得先发请求再等待上游 429。
  5. 绑定/亲和到固定渠道的请求不能悄悄改道;固定渠道满载时返回本地限流错误。
  6. 并发租约必须覆盖整个上游响应生命周期,包括流式响应、取消、错误、超时和重试切换;所有退出路径都必须释放。
  7. RPM 额度在请求被接纳后不回退;并发槽位在请求结束后释放。
  8. 配置热更新必须对新请求生效,不能把旧的容量永久保留在进程内。
  9. 在 Redis 可用的多实例部署中提供全局渠道语义;无 Redis 时明确降级为单实例语义并可观测。
  10. 本期不引入排队,排队应作为独立需求处理,避免队头阻塞和请求取消语义混入准入控制。

建议实现边界

  • 抽取独立的 channel admission/lease 接口,由渠道选择器在候选选择阶段调用。
  • Redis 路径使用原子脚本或等价原子操作,同时完成 RPM 检查和并发租约预留,避免“先探测、后占位”的竞态。
  • 并发租约带唯一 attempt ID 和过期保护;长流需要续租,进程崩溃后租约自动失效。
  • 内存实现仅作为无 Redis 的单实例 fallback,不宣称跨节点全局限制。
  • 未配置限制的渠道保持现有性能路径,不能因为新增能力为每次请求增加无意义的数据库查询。
  • 渠道配置优先复用 ChannelSettings,默认值保持向后兼容,不新增生产数据迁移要求。
  • 准入拒绝、当前占用、RPM 消耗和释放异常应提供后续可观测性所需的计数接口,但不把本 issue 扩展成完整监控页面。

相关实现与不直接引入的原因

  • Nexus #11 跟踪的 上游 PR #6264:有价值,但存在进程内 gate 固化、非原子 key 探测、多实例失真、auto-group/multi-key 排除和热路径查询问题。
  • 上游 PR #4172:仅提供进程内并发计数,无法满足多实例全局语义。
  • 上游 PR #5067:主要是按用户或 Key 维度的速率限制,不能保护渠道聚合 RPM。
  • 上游 PR #6580:改善失败后的渠道排除和冷却,但没有完成主动准入控制。

这些实现可作为参考和 review 背景,但不直接 cherry-pick 当前 head。

验收条件

  • 上游 PR 引用并解决 功能请求:渠道速率限制与并发控制功能 QuantumNous/new-api#1730,提交完整设计说明、迁移/默认值说明和测试。
  • 同优先级存在可用渠道时,满载渠道不会收到上游请求,流量会改选其他渠道。
  • 并发上限在成功、失败、超时、取消、流式结束和重试切换后均无槽位泄漏。
  • RPM 和并发边界在 Redis 多实例场景下保持一致;Redis 不可用时 fallback 语义有测试和文档。
  • 配置从不限变为有限、降低上限、提高上限后,新请求行为正确。
  • 渠道亲和、auto group、优先级和权重行为没有被容量跳过逻辑破坏。
  • 本地准入拒绝不伪装成上游 429,不触发错误渠道自动禁用或额外计费。
  • 覆盖竞态、重复释放、租约过期、长流续租和多 Key 聚合的回归测试。
  • 上游合并并进入正式 release 后,再从 nexus 补丁栈中移除等价本地补丁;在此之前 Nexus 使用独立、可回放的本地补丁。

跟踪计划

  • 在上游分支基于当前 main 重新实现并发/RPM 准入
  • 提交上游 PR 并同步设计和测试结果
  • 跟踪 maintainer review、冲突和 release 落点
  • 上游 PR 合并前,在 nexus 以独立线性补丁回放最终实现
  • 上游正式 release 包含后,按 Nexus patch-stack 规则移除重复补丁

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestupstream candidateWatch upstream; take via upstream if merged, otherwise consider integrating independently.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions