0

0

requests 如何实现带指数退避 + 抖动的自动重试机制

舞夢輝影

舞夢輝影

发布时间:2026-01-23 19:29:02

|

329人浏览过

|

来源于php中文网

原创

requests默认不支持带抖动的指数退避,需通过自定义urllib3.Retry子类(如JitteredRetry)重写get_backoff_time方法注入随机抖动,并挂载到HTTPAdapter;重试失败统一抛出RetryError而非原始异常,须显式捕获;手动循环更灵活但需自行管控超时、Retry-After头及异步适配。

requests 如何实现带指数退避 + 抖动的自动重试机制

requests 默认不支持指数退避重试,必须手动集成 retrying 逻辑

requests 本身只提供基础的 Session 和简单重试(如 urllib3.Retry),但它的内置重试不带抖动(jitter),且指数退避参数控制粒度粗、不可定制抖动范围。真要实现「带抖动的指数退避」,得绕过 requests.adapters.HTTPAdapter 的默认行为,用更底层的 urllib3.util.retry.Retry 配置,或自己封装重试循环。

用 urllib3.Retry 实现带抖动的指数退避(推荐)

这是最轻量、兼容性最好、且不引入额外依赖的方式。关键点在于: - 使用 urllib3.util.retry.Retrybackoff_factor 启用指数退避 - 通过重写 get_backoff_time() 方法注入抖动逻辑 - 将自定义 Retry 实例挂载到 HTTPAdapter

示例代码片段:

import random
import time
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
from requests import Session

class JitteredRetry(Retry): def init(self, jitter=0.2, *args, *kwargs): super().init(args, **kwargs) self.jitter = jitter

def get_backoff_time(self):
    backoff = super().get_backoff_time()
    if backoff <= 0:
        return 0
    # 在 [backoff × (1−jitter), backoff × (1+jitter)] 区间内随机
    return backoff * (1 + random.uniform(-self.jitter, self.jitter))

session = Session() adapter = HTTPAdapter( max_retries=JitteredRetry( total=3, status_forcelist=[429, 500, 502, 503, 504], backoff_factor=1.0, jitter=0.3 # 30% 抖动幅度 ) ) session.mount("https://", adapter) session.mount("http://", adapter)

后续调用 session.get() / session.post() 即自动启用抖动退避

注意:backoff_factor=1.0 表示第 n 次重试前等待约 1 × 2^(n−1) 秒(再乘以抖动系数);jitter=0.3 让每次等待时间在理论值 ±30% 内浮动,有效缓解重试风暴。

requests.exceptions.RetryError 是重试失败的最终异常类型

当所有重试都耗尽后,requests 不会抛出原始网络异常(如 ConnectionError),而是统一包装为 requests.exceptions.RetryError。这点容易被忽略,导致错误处理漏掉重试失败场景。

常见误判写法:

抖云猫AI论文助手
抖云猫AI论文助手

一款AI论文写作工具,最快 2 分钟,生成 3.5 万字论文。论文可插入表格、代码、公式、图表,依托自研学术抖云猫大模型,生成论文具备严谨的学术专业性。

下载
try:
    r = session.get(url)
except requests.exceptions.ConnectionError:
    # ❌ 这里捕获不到重试耗尽后的异常
    handle_failure()

正确做法是:

  • 显式捕获 requests.exceptions.RetryError
  • 或更稳妥地,同时捕获 RetryError 和其他可能未进入重试流程的异常(如 DNS 解析失败发生在首次请求前)
  • 注意:即使启用了重试,超时(Timeout)仍可能直接抛出,不经过 RetryError

手动重试循环比适配器更灵活,但需自行管理状态

如果你需要动态调整退避参数(比如根据响应头中的 Retry-After)、记录每次重试耗时、或在重试中插入日志/监控埋点,用 while 循环手动控制更合适。

核心要点:

  • time.sleep() 控制间隔,别依赖 Retry 类的黑盒逻辑
  • 每次 sleep 前计算抖动:例如 sleep(base_delay * (2 ** attempt) * random.uniform(0.5, 1.5))
  • 务必设置最大尝试次数和总超时上限(避免无限卡住)
  • Retry-After 响应头做优先级高于指数退避的处理

这种写法自由度高,但容易写出阻塞主线程、没做 cancelable、或抖动逻辑重复的代码——尤其在异步环境中,得换用 asyncio.sleep 并配合 async with 生命周期管理。

抖动不是锦上添花,而是分布式系统里避免重试雪崩的关键细节;很多线上故障就卡在「所有客户端在同一毫秒发起重试」这一步。别省略它,也别用固定 delay 模拟抖动。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

234

2023.10.07

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

92

2023.09.25

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

314

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

747

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Laravel 5.8 中文文档手册
Laravel 5.8 中文文档手册

共74课时 | 86.6万人学习

SESSION实现登录与验证
SESSION实现登录与验证

共10课时 | 9.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号