报错是这么冒出来的。tenacity 8.5 用 wait_exponential(multiplier=1, exp_base=2) 重试 10 次,最后一次间隔 1024 秒,接口早就恢复,任务还在睡。
中间走过弯路,把「异常捕获范围过大,把不可重试错误也算了进去」当成主因,改完现象没变。
真正麻烦的地方在于,几个原因的现象几乎一样。没有设置 max 参数,指数没有天花板。也可能是重试次数按总时长估的,实际远超预期。
少数情况下是多个装饰器叠加,退避被乘了两次。
第一件事是打印每次的等待时间
python -c "from tenacity import wait_exponential;w=wait_exponential(multiplier=1,exp_base=2);print([w(i) for i in range(6)])"
接着改用带上限和抖动的策略
python -c "from tenacity import wait_exponential_jitter;w=wait_exponential_jitter(initial=1,max=30,jitter=2);print([round(w(i),1) for i in range(6)])"
只对限流类错误重试
python -c "from tenacity import retry,retry_if_exception_type;print('retry on RateLimitError only')"
等前面都确认过,再用假接口验证总耗时
python -c "print(sum(min(30,2**i) for i in range(6)))"
怎么算真的好了,看的是同一批现象。第 6 次之后等待稳定在 30 秒以内,接口恢复后一个周期内任务继续,成功率不变。
容易忽略的是,退避没有上限等于把故障时间拉长,指数增长的参数一定要配 max 和抖动。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
