Files
pikasTech-unidesk/docs/MDTODO/details/sub2api-upstream-reliability/R2.2.1_Task_Report.md
T

7.0 KiB
Raw Blame History

R2.2.1 客户可见错误溯源与调优建议

范围与数据源

  • 运行目标:PK01 host-DockerSub2API 0.1.153
  • 原生 APIdashboard/overviewupstream-errorsaccount-availabilityconcurrencyrequestssystem-logs/health
  • 原生 system-logs 未索引策略事件,按既定 CLI 规则回退读取 runtime 日志。
  • 观察窗口:连续 20 分钟快照与 60 分钟汇总。
  • 本轮只分析,没有修改 YAML、runtime 配置或 Sub2API 代码。

客户错误率

  • 20 分钟窗口:335 次请求,4 次客户错误,客户错误率 1.19%,上游错误率 2.99%。
  • 60 分钟窗口:907 次请求,8 次客户错误,客户错误率 0.88%,上游错误率 3.64%。
  • 60 分钟内发生 7 次 account_select_failed,几乎覆盖全部客户可见错误。
  • 组并发快照为 9/218,负载 4.13%,排队 0;全池并发不是主因。
  • system-log sink 的 queue、drop 和 write failure 均为 0;日志落库不是业务错误来源。

请求级根因

模型候选为零

  • 三个 gpt-5.4-nano 流式请求分别在 5ms、10ms、28ms 内未选中账号并返回 404。
  • 请求 ID21e5d449-3b0d-4a70-a798-1dc0af0ba11055f7eb2a-b469-4d90-9ec9-3d20d278aef7e90dfd63-22c1-419b-a479-53f860d4151a
  • 官方源码会在组内存在账号但没有任何 model_mapping 支持请求模型时返回 404 model_not_found
  • 这不是瞬时容量问题,重试、临时不可调度和提高切号次数均无效。

多账号连续失败后候选耗尽

  • 8150234d-eee2-4a08-a43e-e47a22274609gpt-5.4account 28 返回 503、account 27 返回 429、account 31 返回 429,约 6.1 秒后无候选,最终 429。
  • bf9aea0a-869a-4ee0-a99c-3b0ceb553822gpt-5.6-lunaaccount 28 返回 503、account 27 返回 429,约 67 秒后上下文取消且无候选,最终 429。
  • 03a94444-ff26-4038-b1b9-67e249ce7f59gpt-5.6-solaccount 33 返回 524、account 31 返回 502,约 180 秒后上下文取消且无候选,最终 502。
  • 5d8f05ff-9cbc-4040-b6eb-4b262ab85f39gpt-5.6-solaccount 33 返回 524,约 126 秒后上下文取消且无候选,最终 502。
  • max_account_switches=10 只是上限。官方实现会排除已失败账号并重新选号;剩余账号不满足模型或运行状态时,会在只切 1 至 3 次后结束。

流式提交后错误

  • 成功样本证明自动 failover 正常工作:account 27 的 502 可切到 account 33account 28 的 503 可切到 account 31。
  • 存在 forward_failed + HTTP 200,例如 account 31 返回 Concurrency limit exceeded,但下游已经提交流式响应。
  • 官方 v0.1.153 在检测到已写入语义响应后明确禁止换号,以免拼接两个上游流。
  • 此类错误不能靠临时不可调度透明恢复,只能减少上游发生率,或由客户端在流中断后重试或恢复。

上游账号主因

  • 60 分钟上游记录共 72 条:rate-limit 24、overload 15、concurrency 12、generic upstream failure 11、status-only 6、model-route-unavailable 4。
  • account 2810 次 overload,当前高频触发 503 临时不可调度。
  • account 27rate-limit 为主,同时有 502 generic failure;现有规则只覆盖 502,不覆盖真实 429 文本。
  • account 3113 次 rate-limit 为主,另有 concurrency 和一次 GROUP_DISABLED;模板未匹配 Upstream rate limit exceeded
  • account 197 次 504,其中 2 次明确 concurrency、1 次 upstream unavailable、4 次只有状态;另有 3 次 No available channel for model
  • account 322 次 429 rate-limit、1 次 502 concurrency。
  • account 29、30:余额不足导致 403,已处于 status=errorschedulable=false,不会继续被调度,但减少了候选容量。

官方版本判断

  • PK01 运行 v0.1.153
  • v0.1.152..v0.1.153 的相关变更是 WebSocket ingress 生命周期限制,不改变当前 HTTP 模型选号、failover 或临时不可调度匹配。
  • v0.1.149 已包含无账号支持模型时返回 404 的实现,因此回退不会消除 gpt-5.4-nano 404。
  • v0.1.153 已包含 compact 心跳不阻断 failover 的官方 #3887 修复。没有证据表明回退能降低当前错误率,不建议回退。

调优建议

P0:修正模型目录与映射

  • 查明 gpt-5.4-nano 是客户端误配、错误广告模型还是预期别名。
  • 若没有真实上游支持,从客户可见模型目录和调用配置中移除。
  • 若业务确实需要,只映射到已经实测支持的真实模型,不能为消除 404 添加虚假映射。

P1:扩展保守临时不可调度模板

  • 在 429 规则增加真实关键词 upstream rate limit exceeded,保持 1 分钟冷却。
  • 新增 504 规则时只加入实测关键词 concurrency limit exceededupstream service temporarily unavailable,保持 1 分钟冷却。
  • 不增加任意 504 规则;4 次 504 只有状态码,不能推断真实原因。
  • 不把 No available channel for model 放入通用账号级模板;这是模型级缺口,账号级摘除会误伤其他模型。
  • lyon9801 继续保持例外,不绑定临时不可调度规则。

P1:账号级并发对照调优

  • 不降低组级并发。
  • account 31 有最强直接并发证据,可先做单账号对照,例如从 30 降到 20,观察 30 至 60 分钟的错误和吞吐。
  • account 19、27、32 也有信号,但没有错误时刻并发历史;不要一次性全降。
  • 手工账号属于 runtime 管理面,后续通过 runtime CRUD 调整,不纳入 YAML managed profile 自动同步。

P1:降低慢失败对客户时间预算的吞噬

  • 524 请求分别在约 126 秒和 180 秒后穿透,第一个慢上游已消耗大部分客户超时预算。
  • 官方默认 gateway.response_header_timeout=600s,明显长于当前客户或边缘上下文。
  • 建议先确认运行实际值,再受控收紧 OpenAI 响应头超时,为一次 failover 预留预算;不能直接照抄固定值。
  • 对照指标应包含首 token 延迟、超时型上游错误、failover 成功率和客户错误率。

P2:恢复候选容量与调度偏好

  • account 29、30 只有补足余额并通过真实请求验证后才能恢复,不能直接改为 schedulable。
  • account 28、27、31 当前优先级高且错误集中,可在确认模型覆盖后降低调度偏好,让更稳定账号先承担请求。
  • Ops system-log 未索引策略事件,60 分钟有 144 条事件依赖 runtime fallback;这不造成业务错误,但限制长期归因,由 R2.3 跟踪。

不建议的措施

  • 不建议回退到 v0.1.149
  • 不建议提高 max_account_switches
  • 不建议降低全池并发。
  • 不建议启用 pool_mode 做同账号重试。
  • 不建议对所有 4xx/5xx 做无关键词临时不可调度。

后续验收

  • 按 20 分钟和 60 分钟双窗口继续观察客户错误率、upstream error rate、account_select_failed、模型 404、failover 成功率、forward_failed + 200 和每账号根因。
  • 每次只改变一个变量并保留前后窗口;R2.2 继续保持进行中。