重试与失败成本是什么
失败重试是要花钱的:超时、限流与网络抖动都会触发重发,于是同一个任务被计费多次。稳健策略包含四件事:按错误类型分级决定是否重试、指数退避加随机抖动、用幂等键防止重复提交,以及对重试率设监控。无退避的重试风暴会把限流升级为更严格的封禁;重试率持续升高说明上游存在真实故障,此时应停止增加次数,改为限流降级或切换备用模型通道。
基本信息
| 触发原因 | 限流、服务端错误、超时、连接重置 |
|---|---|
| 退避策略 | 指数退避加随机抖动,避免同时重试 |
| 重试上限 | 限定次数与总时长,超过快速失败 |
| 幂等控制 | 请求带幂等键,防止重复扣费 |
| 监控指标 | 重试率、失败率与单位成功请求成本 |
| 预算归属 | 重试消耗要计入成本模型,不能只算成功请求 |
典型使用场景
- 批量任务:失败行单独重试而不是整批重跑
- 高峰限流:退避后错峰重发,避免加剧拥堵
- 网络抖动:短超时加有限重试提升成功率
- 成本核算:把重试带来的重复费用计入单位成本
- 故障排查:用重试率变化区分自身问题与上游故障
指数退避实现
指数退避实现
import random, time
def backoff(attempt, base=0.5, cap=8.0):
# 指数增长并乘以抖动,避免集群同时重试造成二次冲击
delay = min(cap, base * (2 ** attempt))
return delay * (0.5 + random.random())
for attempt in range(4):
try:
resp = call_api() # 请求带幂等键,重复提交不会重复计费
break
except RetryableError:
if attempt == 3:
raise # 超过上限快速失败,交给上层降级
time.sleep(backoff(attempt))错误类型与处理
| 错误 | 是否重试 | 处理方式 |
|---|---|---|
| 429 限流 | 是 | 指数退避加抖动,必要时切备用模型 |
| 5xx 服务端 | 是 | 退避重试,超过上限快速失败 |
| 请求超时 | 谨慎 | 先确认是否已产生计费,再带幂等键重发 |
| 4xx 参数错误 | 否 | 重试无意义,直接修正请求 |
| 内容被安全拦截 | 否 | 走审核与拒答流程 |
固定间隔高频重试会触发更严格的限流甚至封禁;重试率持续升高时应排查上游真实故障,而不是继续加次数。
超时请求不一定失败:服务端可能已完成生成并计费,缺少幂等键时重发会造成双份费用与重复入库。