必须显式设置timeout并拆分为(connect_timeout, read_timeout)二元组,connect设3~5秒,read略大于下游p99;重试需用session+urllib3.retry配置,仅针对网络异常及502/503/504,配合backoff_factor和总次数≤3。

requests 调用下游服务时 timeout 参数到底怎么设
不设 timeout 就等于把命交给网络——超时可能卡住整个线程,尤其在高并发下拖垮服务。Python 的 requests 默认不设超时,这是最常被忽略的隐患。
必须显式传入 timeout,且推荐拆成 (connect_timeout, read_timeout) 二元组:
-
connect_timeout控制 TCP 连接建立时间,一般设3~5秒足够;太短容易误判网络抖动,太长会拖慢失败感知 -
read_timeout控制从建立连接后读取响应的时间,应略大于下游服务 P99 响应时长(比如下游 P99 是 800ms,这里设1.5或2.0) - 只传单个数字(如
timeout=5)等价于(5, 5),但 connect 和 read 场景差异大,合并不灵活 - 设成
timeout=None或完全不传,等于无限等待,生产环境严禁
重试不是加个 retry=True 就完事
requests 自带的 Retry 类得手动配,直接写 retry=True 会报错——它根本不是 requests.get() 的参数。
正确做法是构造 Session + urllib3.Retry,关键点在状态码和异常类型的区分:
立即学习“Python免费学习笔记(深入)”;
- 只对可重试错误重试:网络层异常(
ConnectTimeout、ReadTimeout、ConnectionError)和部分 HTTP 状态码(502、503、504),别盲目重试400或401 -
backoff_factor必须设(比如0.3),否则重试是“秒连三发”,可能加剧下游雪崩 - 总重试次数建议 ≤3,再高意义不大,反而延长用户等待
- 示例片段:
from requests.adapters import HTTPAdapter<br>from urllib3.util.retry import Retry<br><br>session = requests.Session()<br>retry_strategy = Retry(<br> total=3,<br> status_forcelist=(502, 503, 504),<br> backoff_factor=0.3<br>)<br>adapter = HTTPAdapter(max_retries=retry_strategy)<br>session.mount("http://", adapter)<br>session.mount("https://", adapter)
异步调用(aiohttp)里 timeout 和 retry 更容易漏配
aiohttp 的 ClientTimeout 和重试逻辑默认全关,不像 requests 至少还有个显眼的 timeout 参数提醒你。
两个硬性动作不能省:
- 创建
ClientTimeout实例并传给ClientSession,例如timeout=ClientTimeout(total=10, connect=3, sock_read=7);不传就按默认5m总超时,线上几乎等于没设 - 重试得自己写循环或用
tenacity这类库,aiohttp本身不提供内置重试;简单轮询要注意加await asyncio.sleep()避免空打 - 注意
raise_for_status()抛出的是aiohttp.ClientResponseError,不是requests.HTTPError,类型判断别写错 - 并发请求下,每个
ClientSession应复用,别在每次请求里新建——否则 DNS 缓存、连接池全失效
超时与重试组合导致的隐蔽问题
你以为设了 3 秒超时 + 3 次重试,最多耗时 9 秒?错。实际可能是 3 × (3s connect + 7s read) = 30 秒,而且中间还夹着退避延迟。
真正要控制的是端到端最大耗时,所以必须做两件事:
- 用外层
asyncio.wait_for()(异步)或signal.alarm()/concurrent.futures.wait()(同步)兜底,强制截断整条调用链 - 重试时记录原始开始时间,每次重试前检查是否已超全局 deadline,避免“重试到一半才发现来不及”
- 下游返回
Retry-After头时,优先按它来休眠,而不是死守backoff_factor - 日志里必须同时打上「发起时间」「重试次数」「当前 timeout 设置」,否则出问题根本分不清是下游慢、重试策略失控,还是上游压根没设限
超时和重试从来不是独立配置项,它们和你的服务 SLA、下游稳定性、熔断阈值是一体的。少一个环节对齐,线上就多一分不可控。










