feat(routing): 会话首请求上游竞速——等权组内择快并绑定亲和
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 42/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- typescript
- 領域
- api, backend, performance
調査の方向性
session-affinity.ts から始めて、既存の重み付き upstream 選択、同時実行の受付、リクエストロギング、failoverHistory の各パスを追跡します。アフィニティミスと最初のバイトのレスポンスがどのように処理されるかを確認し、その後、同一優先度および同一重みでの競合、勝者へのバインディング、敗者の中止、ロギング、グローバルスイッチのテストを定義します。対象となるアフィニティミス以外では既存の選択比率が変わらないことをもって完了とします。
索引モデルが issue の本文から書いたものです。
説明
背景
当前上游选择完全由人工配置驱动:候选集经能力匹配、密钥授权、健康/熔断过滤、并发准入后,按 priority 分层、层内按 weight 加权随机选一个。系统不感知上游的实时快慢,个别请求卡在慢上游时只能等超时后 failover。
请求日志中已有完整的耗时数据,但仅用于事后报表,未参与选路决策。
方案:首请求竞速 + 亲和绑定
利用现有会话亲和性机制(session-affinity.ts,绑定键为 (apiKeyId, capability, sessionId))的 miss/hit 分叉作为竞速触发点:
请求进来 → 查亲和性
├─ 命中 → 直连绑定上游(会话内绝大多数请求,零额外成本)
└─ 未命中 → N 路并发竞速 → 胜者响应并写入绑定 → 本会话后续直连胜者
胜者是实测选出的“此刻对该会话最快的上游”,等于每个会话开头免费做了一次真实探测,且后续请求命中胜者的 prompt cache。
设计决策
| 决策点 | 结论 |
|---|---|
| 触发时机 | 亲和性 miss 且能提取出 sessionId(提不出的请求走原有选路,防止一次性调用每次都竞速) |
| 参赛资格 | 先按现有逻辑加权随机选出“种子”,与种子同优先级且同权重的候选构成竞速组 |
| 参赛人数 | 默认 2,上限 3,组内随机抽取;组内只有种子自身时不竞速,直连 |
| 胜负判定 | 首字节到达且状态码非 5xx;输家立即 abort 流 |
| 绑定 | 胜者写入现有亲和性绑定(TTL 语义不变:滑动 5 分钟 / 绝对 30 分钟) |
| 开关 | 全局开关,默认开启 |
| 记录 | 全部参赛路计入请求日志与计费快照(复用 failoverHistory 结构,竞速≈并行版 failover 首跳) |
参赛资格的语义依据
priority 表达“我更想用谁”,weight 表达“我要谁多承担”——竞速若跨层或跨权重,会用“谁快用谁”推翻这些人工意志。同优先级 + 同权重是配置中唯一“毫无偏好声明”的等价组,现有实现对它们用纯随机;把纯随机换成实测竞速,是不覆盖任何人工配置的升级。
由此天然获得细粒度控制面:想让哪些上游竞速就配成等权同级;不想让某个贵上游参赛,挪 1 点权重即可退出。无需逐上游开关与新增 UI。
种子选组机制保证跨组流量分配比例完全不变(weight 语义原样保留),竞速只发生在等权组内部。
成本与已知取舍
- 竞速不是严格“每会话一次”:亲和绑定 30 分钟到期或空闲超 5 分钟失效后会重新竞速,频率仍然很低。
- 输家上游照付首轮输入 token 费用(或消耗订阅账号一次请求额度),故 N 默认 2、上限 3。
- 等权组内 weight 的分流作用会部分失效(谁快谁赢)。存在一定自平衡:胜者负载升高变慢后开始输,流量自然溢出。额度型限制(如订阅 5 小时窗)不体现在延迟上,耗尽报错后由现有 failover 兜住。
- 已把多个按量付费上游配成等权的存量用户,升级后首轮 token 费会随竞速翻倍,需在发版说明中告知(默认开启的告知义务)。
边界与注意点
- 竞速期间并发槽位短暂占用 N 个,需与队列准入机制正确交互(并发满的候选本就已被过滤出候选集)。
- 胜负判定后输家 abort 必须及时,避免继续产生输出 token。
- 下游响应与错误体不得携带上游身份信息(沿用现有约束)。
不做的事
- 全量竞速(每请求 N 路):成本 ×N,不做;本方案阈值语义上是其安全子集。
- 对冲请求(hedged requests,绑定上游中途卡住时补发备胎):与竞速互补,另行考虑。
- 逐上游“参与竞速”开关与 UI:等权同级配置已是控制面,暂不需要。
- 主要言語
- TypeScript
- スター
- 4
- フォーク
- 0
- 平均マージ
- 10分
- マージ済み PR(30日)
- 3
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートあり
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
g1331/AutoRouter のほかの issue
-
feature
難易度 5/5 1週間以上 初心者へのやさしさ 45/100
g1331/AutoRouter#236 ·
メンテナーはふだん 1 日以内に返信
-
feature
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
g1331/AutoRouter#235 ·
メンテナーはふだん 1 日以内に返信
g1331/AutoRouter の issue をすべて見る
似ている issue
-
難易度 1/5 1〜3時間 初心者へのやさしさ 86/100
g1331/phantom-circuit#93 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
compiler
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
HerringtonDarkholme/hd-lang#1699 ·
メンテナーはふだん 1 日以内に返信
-
account bug communication lecture
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信