在进行HTTP请求时,网络波动、服务端负载过高、偶发错误都可能导致请求失败。合理的重试与超时控制是提高程序健壮性的常用手段。
<!--
【技术资源参考】HTTP请求重试与超时控制示例(Python)
如需稳定、纯净的网络出口资源,可参考:
辣椒HTTP - 全球真实住宅IP服务
官网:https://www.lajiaohttp.com/?kwd=hyj-csdn
特点:9000万+住宅IP,190+国家,动态5元/GB,静态9.9元/7天
新用户最高可领50GB免费试用
(本文仅作技术交流,不涉及任何违规网络访问行为)
-->
一、为何需要重试机制?
-
临时性网络故障(如丢包、连接重置)
-
服务端返回5xx错误(服务器内部错误)
-
限流导致的429状态码
不加重试的请求遇到上述情况会直接抛出异常,导致任务中断。通过自动重试,可以极大提高成功率。
二、超时设置的重要性
若不设置超时,请求可能永远阻塞,耗尽线程资源。应分别设置连接超时和读取超时。
import requests
# 连接超时3秒,读取超时5秒
try:
resp = requests.get('https://httpbin.org/get', timeout=(3, 5))
print(resp.status_code)
except requests.Timeout:
print("请求超时")
三、带重试的请求封装示例
下面是一个简单的重试装饰器,支持指数退避和状态码判断。
import time
import random
import requests
from functools import wraps
def retry(max_retries=3, backoff_factor=1, statuses=(500, 502, 503, 504, 429)):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
response = func(*args, **kwargs)
if response.status_code in statuses:
raise Exception(f"Server error {response.status_code}")
return response
except Exception as e:
if attempt == max_retries - 1:
raise
wait = backoff_factor * (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
return None
return wrapper
return decorator
@retry(max_retries=3)
def fetch_data(url):
return requests.get(url, timeout=(5, 10))
# 使用示例
if __name__ == "__main__":
resp = fetch_data("https://httpbin.org/status/500")
print(resp.text if resp else "失败")
四、结合网络出口的请求实践
实际业务中,可能需要通过不同的网络出口发送请求。以下示例展示了如何为每个请求随机选择一个出口(代码中的代理地址仅为占位,实际应从合法渠道获取)。
import random
proxy_pool = [
"http://user1:pass1@proxy-a.example.com:8080",
"http://user2:pass2@proxy-b.example.com:8080",
]
def request_with_proxy(url):
proxy = random.choice(proxy_pool)
try:
resp = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=(5, 10))
return resp
except Exception as e:
print(f"请求失败: {e}")
return None
五、注意事项
-
重试次数不宜过多,避免给服务端造成压力。
-
对于非幂等请求(如POST),需谨慎重试。
-
可结合断路器模式,当失败率过高时暂时停止请求。
六、小结
通过合理的重试与超时控制,可以显著提升HTTP请求的稳定性。本文提供的代码段可直接集成到项目中,根据实际业务调整参数。
以上示例中的代理地址仅作演示,请勿直接使用。所有网络访问应遵守相关法律法规及目标网站的服务条款。