如何在urllib3的Retry类中使用固定重试间隔而非指数退避?
urllib3自定义Retry类固定重试间隔参数不生效的解决方法
问题场景
想要在urllib3的Retry类中使用固定重试间隔而非指数退避,于是封装了LoggingRetry子类,初始化时指定delay_between_retries=2,但实际重试时该参数始终是默认值0,backoff_factor参数却能正常生效。
问题原因
urllib3在处理重试逻辑时,每次重试都会调用Retry类的new()方法生成新的Retry实例,而原代码没有重写这个方法,导致自定义的delay_between_retries属性无法传递给新实例,新实例会使用该参数的默认值0。
解决方案
重写LoggingRetry类的new()方法,在创建新实例时将当前实例的delay_between_retries属性传递进去,确保每次重试时该参数都能保留初始设置的值。
修改后的完整代码:
import time import urllib3 from urllib3.util.retry import Retry from urllib3.exceptions import MaxRetryError from requests.exceptions import HTTPError import traceback # 带日志的自定义重试策略 class LoggingRetry(Retry): def __init__(self, delay_between_retries=0, *args, **kwargs): print(f"初始化LoggingRetry,delay_between_retries={delay_between_retries}") self.delay_between_retries = delay_between_retries super().__init__(*args, **kwargs) def sleep(self, response=None): backoff = self.get_backoff_time() total_sleep_time = self.delay_between_retries + backoff print(f"LoggingRetry 睡眠 - delay_between_retries: {self.delay_between_retries}, 退避时间: {backoff}") time.sleep(total_sleep_time) # 重写new方法,传递自定义参数 def new(self, **kwargs): # 调用父类new方法生成新实例,同步自定义参数 new_retry = super().new(**kwargs) new_retry.delay_between_retries = self.delay_between_retries return new_retry class MyClient: def __init__(self, total_tries=3, delay_between_retries=0, backoff_factor=0): self.total_tries = total_tries self.delay_between_retries = delay_between_retries self.backoff_factor = backoff_factor # 初始化自定义重试策略 self.retry_strategy = LoggingRetry( total=self.total_tries, status_forcelist=[202], backoff_factor=self.backoff_factor, delay_between_retries=self.delay_between_retries, raise_on_status=False, allowed_methods=frozenset(['GET']) ) # 初始化带重试策略的HTTP客户端 self.http = urllib3.PoolManager(retries=self.retry_strategy, maxsize=4, block=True) def request_data(self, url): try: response = self.http.request('GET', url,) return response except MaxRetryError as me: print(f"达到最大重试次数: {me}") except HTTPError as he: print(f"HTTP错误发生: {he}") traceback.print_exc() except Exception as e: print(f"未知错误发生: {e}") traceback.print_exc() MyClient(delay_between_retries=2, backoff_factor=0).request_data(url='http://0.0.0.202/')
验证效果
运行修改后的代码,每次重试时会打印出delay_between_retries: 2,说明固定间隔参数已生效,每次重试会睡眠2秒(因backoff_factor=0,总睡眠时长等于固定间隔)。
内容的提问来源于stack exchange,提问作者JMortey
相关产品推荐
相关产品推荐

