你去面试,面试官问你:“HTTP请求超时了,你怎么排查?”
你说:“设置个超时时间呗。”
面试官笑了笑,你出去等通知。
这不是在讲笑话,这是真实发生过的场景。超时,听起来简单,但能把这事说清楚的人,不多。
一、你以为的超时不是你以为的超时
很多同学写的代码是这样的:
response = requests.get(url, timeout=5)
然后跑到服务器上,看到日志里一堆Timeout异常,就傻眼了。
来,跟我念一遍:timeout=5的意思不是“5秒内必须返回结果”,而是“5秒内必须完成TCP连接+TLS握手+服务器处理+响应返回”。
任何一个环节超时,都叫超时。
二、TCP连接:三次握手的代价
你以为HTTP是发个请求就行了?太年轻。
正常情况下,建立一个TCP连接需要:
- 客户端发送SYN(时间忽略不计)
- 服务器返回SYN-ACK(通常几十毫秒)
- 客户端发送ACK(时间忽略不计)
这叫三次握手,看起来很美好。但是!如果你DNS解析慢、跨运营商、或者服务器负载高,一次握手可能就要500ms。你设置3秒超时?留给服务器处理的时间就只剩2.5秒了。
更坑的是,如果服务器端口根本没监听,TCP会等很久——因为要等重试机制触发才会放弃。通常是timeout时间用完才给你返回连接超时。
三、TLS握手:你以为的安全代价
HTTPS已经是标配了,但这玩意儿是有成本的。
一次完整的TLS握手需要:
- 1-RTT 或 2-RTT(看你用的TLS版本和Cipher Suite)
- 证书校验(涉及DNS查询和CRL/OCSP查询)
- 密钥交换计算(RSA或ECDHE)
如果你用TLS 1.3,首次连接至少要1-RTT;复用session可以做到0-RTT,但不是所有场景都能用。
实测数据:一次TLS握手平均增加100-300ms延迟。在高并发下,这个数字会更高。
所以如果你HTTPS请求设置timeout=1秒,基本等于自杀。
四、服务器处理:这个才是大头
连接建立了,握手完成了,现在开始真正干活。
服务器处理时间 = 网络IO等待 + 数据库查询 + 业务逻辑 + 响应序列化 + 各种中间件
在微服务架构下,一个请求可能经过:网关 → 认证服务 → 业务服务A → 业务服务B → 数据库 → 缓存 → 业务服务A → 网关
每个环节都可能拖你后腿。而你的客户端超时配置,根本不知道这些内部链路有多长。
五、正确的超时配置姿势
先说结论:超时配置要分层,没有银弹。
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# 创建session并配置适配器
session = requests.Session()
# 连接超时:TCP三次握手时间
# 建议:3-10秒,取决于网络环境
connect_timeout = 5
# 读取超时:等待服务器响应的最大时间
# 建议:30-60秒,看业务逻辑复杂度
read_timeout = 30
# 合并设置
session.get(url, timeout=(connect_timeout, read_timeout))
但是!上面这只是最基础的配置。真正健壮的HTTP客户端,还要考虑:
1. 重试机制
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504],
allowed_methods=["GET", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
2. 熔断降级
当错误率超过阈值,自动熔断,不再发请求去送死。
3. 渐进式超时
第一次重试用短超时,探测系统状态;后续重试逐步增加等待时间。
六、实战经验总结
说了这么多,来点能直接抄的:
- 不要用单一timeout参数,分开设置connect和read
- 连接超时宁可设长一点,跨地域、跨运营商的场景,5秒起步
- 读取超时根据业务逻辑动态调整,简单查询10-15秒,复杂计算60秒起步
- 高并发场景下连接池比timeout更重要,复用连接减少握手开销
- 监控!监控!监控!超时时打日志,记录是连接超时还是读取超时,方便排查
七、最后说句实在话
很多人觉得超时配置是个小问题,但恰恰是这种“小问题”,会在生产环境给你狠狠一击。
你的系统平时好好的,流量一上来就开始各种超时。为什么?因为流量低的时候,服务器响应快、连接池够用;流量一高,响应变慢、连接池打满,然后超时就开始了。
所以,超时配置不是调参,是架构设计。从连接管理、重试策略、熔断降级、监控告警,一个都不能少。
下次面试官问你这个问题,希望你能说得比他预期更多。