事情本身不复杂,线索都在日志里。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 值得重试,其余重试只会放大账单和日志噪音,判断写在最外层比散落在各个调用点可靠。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
