# R2.2.1 客户可见错误溯源与调优建议 ## 范围与数据源 - 运行目标:PK01 host-Docker,Sub2API `0.1.153`。 - 原生 API:`dashboard/overview`、`upstream-errors`、`account-availability`、`concurrency`、`requests`、`system-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。 - 请求 ID:`21e5d449-3b0d-4a70-a798-1dc0af0ba110`、`55f7eb2a-b469-4d90-9ec9-3d20d278aef7`、`e90dfd63-22c1-419b-a479-53f860d4151a`。 - 官方源码会在组内存在账号但没有任何 `model_mapping` 支持请求模型时返回 `404 model_not_found`。 - 这不是瞬时容量问题,重试、临时不可调度和提高切号次数均无效。 ### 多账号连续失败后候选耗尽 - `8150234d-eee2-4a08-a43e-e47a22274609`:`gpt-5.4`,account 28 返回 503、account 27 返回 429、account 31 返回 429,约 6.1 秒后无候选,最终 429。 - `bf9aea0a-869a-4ee0-a99c-3b0ceb553822`:`gpt-5.6-luna`,account 28 返回 503、account 27 返回 429,约 67 秒后上下文取消且无候选,最终 429。 - `03a94444-ff26-4038-b1b9-67e249ce7f59`:`gpt-5.6-sol`,account 33 返回 524、account 31 返回 502,约 180 秒后上下文取消且无候选,最终 502。 - `5d8f05ff-9cbc-4040-b6eb-4b262ab85f39`:`gpt-5.6-sol`,account 33 返回 524,约 126 秒后上下文取消且无候选,最终 502。 - `max_account_switches=10` 只是上限。官方实现会排除已失败账号并重新选号;剩余账号不满足模型或运行状态时,会在只切 1 至 3 次后结束。 ### 流式提交后错误 - 成功样本证明自动 failover 正常工作:account 27 的 502 可切到 account 33,account 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 28:10 次 overload,当前高频触发 503 临时不可调度。 - account 27:rate-limit 为主,同时有 502 generic failure;现有规则只覆盖 502,不覆盖真实 429 文本。 - account 31:13 次 rate-limit 为主,另有 concurrency 和一次 `GROUP_DISABLED`;模板未匹配 `Upstream rate limit exceeded`。 - account 19:7 次 504,其中 2 次明确 concurrency、1 次 upstream unavailable、4 次只有状态;另有 3 次 `No available channel for model`。 - account 32:2 次 429 rate-limit、1 次 502 concurrency。 - account 29、30:余额不足导致 403,已处于 `status=error`、`schedulable=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 exceeded` 和 `upstream 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 继续保持进行中。