requests默认使用连接池是因为底层urllib3默认启用连接池,每次请求复用tcp连接以减少握手开销;默认池大小为10,空闲连接保留120秒,服务端返回connection: close时立即移除连接。

requests 为什么默认用连接池
因为 requests 底层用的是 urllib3,而 urllib3 默认启用连接池——不是“可选功能”,是它处理 HTTP 请求的默认方式。不手动干预时,每次调用 requests.get() 都会尝试复用已有 TCP 连接,而不是每次都新建。
这能省掉三次握手、TLS 握手开销,尤其在高频请求同一域名时,延迟下降明显。但前提是:目标服务支持 HTTP/1.1 的 Keep-Alive,且没主动断连。
- 默认池大小是
10(pool_connections和pool_maxsize均为 10) - 空闲连接最长保留
120秒(pool_block=False时超时抛异常,不是阻塞等待) - 若服务端发了
Connection: close,连接立刻从池中移除,不复用
如何控制连接池大小和复用行为
靠 requests.Session() 配置底层 urllib3.PoolManager。直接改 Session 的 adapter 是唯一可靠方式。
常见错误是以为设置全局变量或改 requests 模块属性就能生效——不行,每个 Session 独立管理自己的池。
立即学习“Python免费学习笔记(深入)”;
- 增大池容量:
s = requests.Session()<br>s.mount('https://', requests.adapters.HTTPAdapter(pool_connections=20, pool_maxsize=20)) - 禁用复用(调试用):
requests.get(url, headers={'Connection': 'close'}),但只对单次请求有效 - 想强制复用,得确保服务端返回
Keep-Alive,且客户端没设Connection: close
ConnectionPoolMaxSizeError 是什么情况
这是 urllib3 抛的 MaxRetryError 子类,本质是池满 + pool_block=False(默认值),导致新请求拿不到空闲连接。
典型场景:并发高、池太小、响应慢,连接长期被占着。不是网络故障,是资源调度卡住了。
- 现象:
MaxRetryError: HTTPSConnectionPool(host='x', port=443): Max retries exceeded with url: / (Caused by PoolFullError(...)) - 别急着加池大小——先看是否请求没及时关闭(比如忘了
.close()或没用with)、响应体没读完(response.content没触发读取) - 真正要调参时,优先调
pool_maxsize,pool_connections只影响不同 host 的池数量,一般不用动
长连接失效后怎么自动重试
连接池本身不负责重试逻辑,靠 urllib3.Retry 控制。但注意:连接复用失败(比如 socket 已断)触发的重试,和业务层 HTTP 5xx 重试是两回事。
默认只对连接级错误(如 ConnectionError、Timeout)重试,不对 404 或 500 重试——除非你显式配置 status_forcelist。
- 启用连接失败自动重试:
adapter = requests.adapters.HTTPAdapter(max_retries=3)<br>s.mount('https://', adapter) - 重试会换新连接(可能新建 TCP),不是“继续用旧连接”
- 如果服务端在 Keep-Alive 期间突然关连接,第一次请求大概率失败,第二次才成功——这就是重试在起作用
池里的连接状态是懒检测的,只有真正用时才发现断了。所以别指望“定期心跳”,实际就是靠失败+重试兜底。










