这个坑值得记一笔。接口设了 5 次重试,指数退避从 2 秒翻到 32 秒,一次故障里请求耗时 90 秒才返回失败,前端 30 秒就超时了,用户看到白屏。
刚开始盯着「4xx 也被重试,白等了好几轮」,折腾了半个多小时,排掉了。
原因不止一个,得分开看。重试总预算没设上限,单次退避叠加超预期;读超时与重试次数独立配置,没有联合约束;同步接口里做重试,占着连接不放。
量出各次重试的实际耗时分布
python -c "import json;rs=[json.loads(l) for l in open('retry.jsonl')];print(sorted(r['elapsed'] for r in rs)[-5:])"
给重试加总预算,超预算直接失败
python retry_cli.py --max-total 25 --max-attempts 3 --backoff 2
只对 429 和 5xx 重试,跳过 4xx
python -c "print({'retry_on':[429,500,502,503,504]})"
等前面都确认过,再把同步重试改成异步补投递
python enqueue.py --topic llm_retry --payload job.json
别只看报错消失,验证要多做一步。故障场景下接口在 25 秒内返回明确失败,前端不再空白等待,补投任务在后台完成并回写结果。
这里还有个坑。重试是为了提高成功率不是为了兜住所有错误,总预算要和上游超时对齐,否则重试本身成了故障放大器。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
