Python requests 重试与超时:给接口调用加三层保护

举报
yd_229284667 发表于 2026/11/07 06:29:22 2026/11/07
【摘要】 给 Python requests 调用加三层保护:用超时卡住单次等待、用可重试规则消化短暂抖动、用总时限与熔断守住系统整体,让偶发故障在用户感知到之前被消化掉。

调用第三方接口时,最常见的故障有三类:网络抖动、服务端短暂过载、DNS 解析偶发失败。没有保护的代码往往在第一次异常时就直接崩掉,或者更糟——无限期挂住,拖垮整个服务。本文给 requests 调用加三层保护:超时、重试、熔断与总时限,三层分工不同,互相配合。

第一层:超时——先给每一次等待设上限

requests 默认没有超时。一次调用可能在连接阶段就挂住,也可能在等响应体时一直等下去。正确做法是把连接超时和读取超时分开设置:

import requests

resp = requests.get(url, timeout=(3, 10))

timeout=(3, 10) 表示建立连接最多等 3 秒,读取响应最多等 10 秒。只传一个数字时,连接和读取共用同一个上限,容易把响应慢但正常的接口误判为超时。超时值不要拍脑袋定:按接口的 P99 耗时来设,内部服务可以短一些,跨公网的第三方接口要留足余量。

第二层:重试——只对值得重试的失败重试

不是所有失败都值得重试。连接异常、502、503、504 这类“可能只是暂时的”失败可以重试;400、401、404、422 这类请求本身有问题的失败,重试多少次结果都一样。用 urllib3 的 Retry 配合 HTTPAdapter 可以把规则写清楚:

from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[502, 503, 504],
    allowed_methods=["GET", "HEAD"],
)
adapter = HTTPAdapter(max_retries=retry)
session = requests.Session()
session.mount("https://", adapter)
session.mount("http://", adapter)

退避因子设为 1 时,重试间隔大约是 0、2、4 秒,指数退避既给了服务端恢复时间,又不会把调用方拖垮。重试次数不要设得太高:下游已经过载时,大量客户端同时重试就是二次冲击。

POST 等非幂等请求默认不要重试,因为不知道第一次请求是否已经生效。如果确实需要重试写操作,先确认接口支持幂等键,再在请求头里带上 Idempotency-Key,让服务端能识别重复提交。

第三层:熔断与总时限——别让一次故障拖垮整个服务

重试只能应对短暂故障。如果下游持续不可用,继续重试只会耗尽连接池和线程。这时需要两道防线:一是给整个操作设总时限,二是简易熔断。

import time

import requests

deadline = time.monotonic() + 30  # 整个操作最多 30 秒
while time.monotonic() < deadline:
    try:
        resp = session.get(url, timeout=(3, 10))
        resp.raise_for_status()
        break
    except requests.RequestException:
        if time.monotonic() >= deadline:
            raise
        time.sleep(1)

总时限保证无论重试多少次,调用都不会超过 30 秒。熔断则是在此基础上再进一步:记录连续失败次数,达到阈值后在一段时间内直接拒绝请求,而不是每次都去撞墙;等冷却期过了再放少量请求探路,成功了恢复,失败了继续熔断。

最后别忘了可观测性:把超时、重试次数、最终失败率记到日志和监控里。没有这些数字,超时和重试参数永远只能靠猜,也没法判断某次故障到底是网络问题还是下游真的挂了。

三层如何配合

三层不是互相替代,而是分工:超时保证单次调用不挂死;重试消化短暂抖动;熔断和总时限守住系统整体。落地时建议:超时按接口 P99 设定、重试只覆盖幂等请求和可恢复状态码、熔断阈值先宽后严、所有参数做成配置项而不是写死在代码里。接口调用的健壮性不是某一个参数,而是一组互相配合的边界。把这三层加好,绝大多数偶发故障都会在用户感知到之前被消化掉。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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