用 Python requests 写带重试与超时的 HTTP 客户端实战

举报
yd_229851404 发表于 2026/11/04 06:05:51 2026/11/04
【摘要】 在日常开发中,调用第三方 HTTP 接口是最常见的任务之一。很多新手直接写 requests.get(url) 就上线,结果一遇到网络抖动、服务端偶发 500,程序就直接崩溃或无限挂起。本文结合一个真实的服务间调用场景,讲清楚超时与重试这两个最容易被忽视、却最关键的细节。 一、先说超时:别让一次请求拖垮整个服务requests 默认没有超时时间。一次 requests.get(url) 如果...

在日常开发中,调用第三方 HTTP 接口是最常见的任务之一。很多新手直接写 requests.get(url) 就上线,结果一遇到网络抖动、服务端偶发 500,程序就直接崩溃或无限挂起。本文结合一个真实的服务间调用场景,讲清楚超时与重试这两个最容易被忽视、却最关键的细节。

一、先说超时:别让一次请求拖垮整个服务

requests 默认没有超时时间。一次 requests.get(url) 如果遇到服务端假死、网络黑洞,调用方会一直等下去,线程池被占满后整个服务雪崩。正确做法是每次请求都显式传 timeout,而且要区分连接超时和读取超时:

# 连接超时 3 秒,读取超时 10 秒
resp = requests.get(url, timeout=(3, 10))

连接超时管的是 TCP 建连和 TLS 握手阶段,读取超时管的是发出请求后等待首字节的时间。把两者分开写,比只写一个数字更能反映真实情况:内网服务建连通常很快,读取超时可以放宽;跨公网调用则相反。

二、重试:不是简单地套个 for 循环

网络抖动、网关 502/503、连接重置,这类瞬时故障重试一次往往就能成功。但重试不能无脑循环,要遵守三条原则:只重试可重试的错误、限制次数、带退避间隔。requests 配合 urllib3 的 Retry 是标准做法:

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

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

resp = session.get("https://api.example.com/data", timeout=(3, 10))
resp.raise_for_status()

backoff_factor=0.5 意味着重试间隔按 0.5 秒、1 秒、2 秒指数退避,避免在服务端已经过载时继续雪上加霜。status_forcelist 只对 502、503、504 这类明确的服务端瞬时故障重试,404、400 这种客户端错误重试没有意义。

三、只对幂等请求自动重试

这是最容易踩的坑。GET、HEAD、PUT、DELETE 是幂等的,重试安全;POST 下单、扣款这类非幂等操作一旦重试,可能造成重复下单。上面的 allowed_methods 只放了 GET、HEAD、OPTIONS,就是这个原因。如果业务必须对 POST 做重试,一定要让服务端支持幂等键:

import uuid

headers = {"Idempotency-Key": str(uuid.uuid4())}
session.post(url, json=payload, headers=headers, timeout=(3, 10))

服务端用幂等键去重,即使请求真的发了两次,也只会执行一次。

四、生产环境还要补齐的三件事

  1. 日志:每次重试都记录日志,包括第几次重试、失败原因、耗时,方便事后定位是网络问题还是服务端问题。
  2. 熔断:连续失败达到阈值就短暂熔断,直接快速失败,别再拿请求去压已经出问题的下游。
  3. 会话复用:用 Session 复用 TCP 连接,减少每次建连的开销;同时设置连接池大小,避免并发一高就排队。

结语

超时和重试看起来只是两个参数,背后却是可用性工程的基本功:超时保护自己,重试包容偶发故障,幂等保证重试安全。把这三点写进团队的 HTTP 客户端封装里,下次再遇到网络抖动,至少不会是半夜被叫醒的那种故障。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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