以下是一个使用 Python 实现的、具有指数退避(exponential backoff)策略的重试装饰器的完整示例:
import time
import functools
import random
def exponential_backoff_retry(max_retries=3, base_delay=1, max_delay=None, jitter=True):
"""
一个具有指数退避策略的重试装饰器。
参数:
max_retries (int): 最大重试次数,默认为3次。
base_delay (float): 初始延迟时间(秒),默认为1秒。
max_delay (float): 最大延迟时间(秒),默认为None(无限制)。
jitter (bool): 是否添加随机扰动,默认为True。
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
retry_count = 0
while retry_count < max_retries:
try:
return func(*args, **kwargs)
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
raise e # 超过最大重试次数,抛出异常
# 计算等待时间
delay = base_delay * (2 ** (retry_count - 1))
if jitter:
delay *= random.uniform(0.5, 1.5) # 添加随机扰动
if max_delay is not None:
delay = min(delay, max_delay) # 限制最大延迟时间
print(f"Function {func.__name__} failed with error: {str(e)}")
print(f"Retrying... (attempt {retry_count}/{max_retries})")
print(f"Waiting for {delay:.2f} seconds before next retry.")
time.sleep(delay)
return None # 如果所有重试都失败,返回None
return wrapper
return decorator
# 使用示例
@exponential_backoff_retry(max_retries=5, base_delay=2, max_delay=30, jitter=True)
def unreliable_function():
"""一个可能会失败的函数"""
import random
if random.random() < 0.7: # 70%的概率模拟失败
raise Exception("Operation failed!")
return "Success!"
# 测试
result = unreliable_function()
print(f"Final result: {result}")
参数说明
- max_retries: 最大重试次数,默认为3次。
- base_delay: 初始延迟时间(秒),默认为1秒。
- max_delay: 最大延迟时间(秒),默认为
None
(无限制)。 - jitter: 是否添加随机扰动,默认为
True
。
工作原理
- 装饰器结构: 使用 Python 的装饰器模式,
exponential_backoff_retry
是一个返回装饰器的高阶函数。 - 重试逻辑: 在
wrapper
函数中实现重试逻辑,每次调用目标函数时捕获异常。 - 指数退避计算: 每次重试时,根据公式
delay = base_delay * 2^(retry_count - 1)
计算等待时间。 - 随机扰动: 如果启用了
jitter
,会在计算的延迟时间基础上乘以一个随机因子(0.5到1.5之间),以避免多个客户端同时重试导致的冲突。 - 最大延迟限制: 如果设置了
max_delay
,确保延迟时间不会超过该值。
使用方法
将装饰器应用到需要重试的函数上:
@exponential_backoff_retry(max_retries=5, base_delay=2)
def your_function():
# 可能会失败的操作
pass
示例输出
当函数失败时,装饰器会按照指数退避策略进行重试,输出类似以下内容:
Function unreliable_function failed with error: Operation failed!
Retrying... (attempt 1/5)
Waiting for 1.23 seconds before next retry.
Function unreliable_function failed with error: Operation failed!
Retrying... (attempt 2/5)
Waiting for 3.45 seconds before next retry.
...
这个装饰器在处理可能会失败的操作(如网络请求、外部服务调用等)时非常有用,通过指数退避策略可以有效减少对目标服务的压力并提高操作的成功率。