Skip to content

feat(gateway): 凭证池表达入口×协议×型号×key,并按策略动态分配 #843

Description

@xiaocheny214

背景

#841 / #842 把 i2v 在途和 429 收成「每把视频 key 一条车道」。这只是同一协议面上的并发舱壁,不是凭证池:

  • 成员来自 env CSV,身份是 primary.key{i}。头部插入或删掉中间一把 key,Redis 冷却/在途会戴到另一把物理钥匙上。
  • 入口(base_url)、协议(family)、型号、key 被压成一张扁平路由表,表达不了一对多 / 多对多:同一 URL 多把 key、同一入口多种协议(OpenAI videos vs FAL queue)、入口目录与 key 授权型号可以不同。
  • 没有加入 / 摘除 / 排干;AUTH 失败不会把 key 移出选路。
  • Admit 与 Gateway 各持一份名单;熔断在进程内存,429 冷却在 Redis。

第一版 Gateway 设计明确「不做自建 key 池」。key 变多、吞吐要按凭证摊之后,需要把池子建全。

多 key 能降低 429 概率,仅当上游配额挂在单把 key 上。现网 #841 的观测(同一秒第三枪 429)还分不清是「单 key 并发=2」还是「整个聚合账号并发=2」。若是账号限额,#842 再按 key 分车道并加 key,等于用 N×2 去撞同一条配额。

相关:#841 #842

目标

  • 可调度单元是兼容边 (credential, endpoint, protocol, model),不是 CSV 下标。
  • 增加 Account 实体:上游把 429/在途挂在哪一个计费主体上。一把或多把 Credential 同属一个 account_id。
  • Model → Protocol 仍是代码里的 family 事实(不配请求形状)。Endpoint×Credential、Account×Credential、Endpoint×Model、Credential×Model 允许 N:M。
  • 选路沿用已有策略:先型号,再过滤兼容边,再按 quota_scope 占坑。
  • 尚未 job_id 的排队可再平衡;已建单粘住原 (credential, endpoint),poll 不换边。
  • 池可维护:稳定 id(禁止 key{i})、加入、disable、drain、摘除;AUTH/欠费 disable。

账号限流如何扩展

HTTP 仍用某一把 key 发出去(job 必须粘在创建它的那把钥匙上),但占坑和 429 冷却记在 Account 上。不必换数据结构,只加一层 Redis 键。

Account
  inflight SET        真正的在途上限,默认仍 2
  cooling / cooldown / shot
  credentials[]       只负责鉴权与粘性

Credential
  可选自己的 SET      AUTH 隔离,或上游「账号 + 单 key rpm」双限额

占坑

429

  • 任一把 key 429 → 冷却整个账号;冷却到期全账号只补一枪。
  • 同账号换 key 不是降级,换了还是打同一条配额。FALLBACK_KEY 在账号限额 + 429 时不要换邻 key;应延迟再打,或切到另一个 account_id / Endpoint。
  • AUTH 只 disable 那一把 key;账号欠费则整账号禁用。

账号限额下如何加吞吐

  • 加同账号 key 不增加在途上限。
  • 只能:确认上游并发后提高 account_inflight_max;再开一个 Account(另一套登录/项目);或确认限额不跟账号走再加 Endpoint。
  • 现网多把 CSV key 若实际共账号,应配成同一个 account_id,否则会按 key 数放大并发去撞 429。

判断现网是哪一种

  • 账本里只有一把 key 429、邻 key 仍成功 → quota_scope=credential。
  • 所有 key 同一秒一起 429 → account(或 endpoint)。

从 #842 长上去

现 #842 账号扩展
inflight:{lane} inflight:acct:{account_id} 为主;inflight:cred:{credential_id} 为可选内层
cooling:{lane} cooling:acct:{account_id}
shot:{lane} shot:acct:{account_id}
FALLBACK_KEY 改挂邻 key 同账号 429 不改挂;有第二账号/入口才切

终态释放必须同时丢掉账号坑和凭证坑,否则整账号会被孤儿 claim 卡死(与 #842 评审同一类问题)。

分期(不要一个 PR 做完)

  • P0 稳定 credential_id,从现有 env 导入;fix(i2v): 全站在途名额与 429 冷却,避免动作建单打满上游 #842 车道键迁过去。追加 key 不再打乱旧车道。
  • P1 disable / drain / AUTH 摘选路;未提交可再平衡;熔断与冷却都挂稳定 id,跨 worker 可见。
  • P2 显式 Endpoint×Model / Credential×Model 目录;无目录时与现网「同 family 都能打」兼容。
  • P3 账号舱壁:quota_scope=account 占 inflight:acct:;同账号 429 冷却账号且不换 key;第二账号/入口才是扩吞吐。可选每凭证提交速率(防齐射)。

P0 可单独合。账号舱壁不依赖 P2 目录,但必须在把「多 key」当吞吐手段之前落地。

验收标准

  • 配置中部删 key 或头部插 key,旧任务的在途/冷却仍绑原物理凭证
  • 新 key 加入后,未 submit 的排队能分到它;已有 job_id 的不换凭证
  • disable 的 key 不再被新占坑;其上已建单仍能 poll 到终态
  • 有目录后,不会把 video.fal_queue 型号派到只会 OpenAI videos 的边上
  • 同一 account_id 且 quota_scope=account 时:3 把 key 也最多 account_inflight_max 路在途;第 N+1 个任务排队,不向邻 key 再 submit
  • 账号下任一 key 429:同账号其它 key 在冷却期内不得 submit;冷却到期全账号只补一枪
  • 账号限额下 Gateway 不因 429 把任务改挂到同账号另一把 key
  • 两个 account_id 时,各自独立在途上限(这才是账号限额下的扩吞吐)
  • 未配 account_id 时退化为每把 key 自己一个账号(fix(i2v): 全站在途名额与 429 冷却,避免动作建单打满上游 #842 行为)
  • 429 不把该 key 熔 60s;52x 仍熔 Endpoint
  • fix(i2v): 全站在途名额与 429 冷却,避免动作建单打满上游 #842 回归:quota_scope=credential 下每凭证在途上限、冷却不连坐、终态释放孤儿 claim;账号模式终态释放账号坑 + 凭证坑

备注

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions