让 Python API 重试更可靠:幂等、退避与时间预算

举报
yd_294777097 发表于 2026/10/30 12:39:53 2026/10/30
【摘要】 从幂等性判断、错误筛选到指数退避,结合 requests 示例说明如何限制重试风险与整体耗时。

API 调用偶尔超时或返回 5xx 很正常,但“失败就重试”可能把短暂故障放大成流量风暴,也可能让订单重复创建。设计重试时,先判断错误是否暂时、请求能否安全重复,以及重试最多占用多久。


先看幂等性。GET、HEAD 通常可重复读取;创建订单、扣款等 POST 可能已经在服务端成功,只是响应丢了。只有当服务端支持幂等键时,才应在多次尝试中复用同一个 Idempotency-Key。否则写操作遇到读超时,应先查询结果或走业务补偿,不能把“没收到响应”当成“没有执行”。


再筛选错误。连接超时、连接重置,以及 408、429、500、502、503、504 往往可以重试;参数错误、鉴权失败等明确的 4xx 通常应直接返回。遇到 429 或 503 时,还要尊重服务端给出的 Retry-After。


下面是一个简化示例:只重试可重复的读取请求,或明确带有幂等键的调用;超时分别限制连接和读取时间,并使用带随机抖动的指数退避。


import random, time, requests

RETRYABLE = {408, 429, 500, 502, 503, 504}


def request(session, method, url, *, key=None, attempts=4):

    method = method.upper()

    safe = method in {"GET", "HEAD", "OPTIONS"} or bool(key)

    headers = {"Idempotency-Key": key} if key else {}

    for attempt in range(attempts):

        try:

            response = session.request(method, url, headers=headers, timeout=(3, 10))

        except (requests.Timeout, requests.ConnectionError):

            if not safe or attempt == attempts - 1:

                raise

        else:

            if response.status_code not in RETRYABLE or not safe or attempt == attempts - 1:

                return response

        time.sleep(random.uniform(0, min(8, 0.5 * 2 ** attempt)))


上线前还要给整个业务流程设置 deadline,避免每次超时和等待累加到不可接受的时长。重试放在一个清晰的调用层,记录错误类型、尝试次数和总等待时间,方便观察真实效果。重试只能缓冲短暂波动;依赖长期不可用时,应快速失败、限流或熔断,给系统留出恢复空间。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。