事情本身不复杂,线索都在日志里。key 过期后客户端按指数退避重试,401 被当成可重试错误,单条请求刷了 300 次,日志里 401 占满两页,真正的 403 配额问题反而被埋掉。

第一反应是「重试只看总时长,没有设置尝试次数上限」,验证下来不成立。

排查方向其实有限,先把可能性排一排。重试策略只按 5xx 和网络异常分支写,4xx 落到了兜底分支。还有一种是SDK 自带重试与业务重试叠加,次数相乘。

不容易想到的是,401 的错误体里带 retry 字样,被正则误判成可重试。

第一件事是把各类状态码的重试次数打出来

python -c "import json,collections;print(collections.Counter(r['status'] for r in json.load(open('retry.log.jsonl'))))"

然后把 4xx 明确列进不可重试清单

python -c "print([400,401,403,404,422])"

给重试加尝试次数与总时长双上限

python -c "print({'max_attempts':3,'max_elapsed':20})"

末了用无效 key 触发一次 401 验证不再重试

curl -s -o /dev/null -w '%{http_code}\n' https://api.openai.com/v1/models -H "Authorization: Bearer sk-invalid"

恢复的判定其实很直接。用无效 key 请求只出现一次 401,日志里不再有重试记录,正常请求的重试次数与改动前一致。

补一句。4xx 里只有 408、409、429 值得重试,其余重试只会放大账单和日志噪音,判断写在最外层比散落在各个调用点可靠。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189