requests.Session()默认连接池扛不住高并发,因其pool_connections和pool_maxsize均默认为10,50并发时连接池迅速占满,触发“Max retries exceeded”或“Connection pool is full”错误;必须显式配置更大连接池并合理设置重试策略。

requests.Session() 的默认连接池为什么扛不住高并发?
Python 3.9+ 中 requests 默认使用 urllib3 的 HTTPConnectionPool,最大连接数是 10(pool_connections 和 pool_maxsize 均默认为 10)。并发发起 50 个请求时,大量请求排队或直接抛出 Max retries exceeded with url 或 Connection pool is full 错误——这不是网络问题,是连接池被占满后拒绝新连接。
- 必须显式配置
pool_connections(Session 级连接池数量)和pool_maxsize(单个池最大连接数),二者通常设为相同值 -
max_retries设太低会导致失败快,太高会掩盖连接池瓶颈;建议设为3或urllib3.Retry(3) - 不要复用同一个
Session实例跨线程/协程而不加锁——Session不是线程安全的,但可安全用于单线程 + 异步(如asyncio配合aiohttp)
用 asyncio + aiohttp 替代 requests 处理高并发更合理
requests 是同步阻塞库,靠多线程硬扛并发时,线程切换和连接池争抢反而加剧资源耗尽。Python 3.9+ 的标准异步生态已稳定,aiohttp 原生支持连接池复用、超时控制和信号量限流,更适合爬虫场景。
- 创建
aiohttp.ClientSession时传入connector=aiohttp.TCPConnector(limit=100, limit_per_host=30),避免单域名打爆 - 务必用
async with session.get(url),而不是session.get()——后者不自动关闭响应体,导致连接泄漏 - 配合
asyncio.Semaphore控制并发总数,比如sem = asyncio.Semaphore(50),每个请求前await sem.acquire(),结束后sem.release() - 错误处理要覆盖
aiohttp.ClientError和asyncio.TimeoutError,不能只抓Exception
requests + ThreadPoolExecutor 下如何安全调优连接池?
如果必须用 requests(例如依赖某些同步中间件),就别用全局 Session,而是为每个线程分配独立 Session 实例,并关闭其连接复用以减少竞争。
- 在
ThreadPoolExecutor的initializer中为每个线程初始化专属Session:thread_local.session = requests.Session() - 设置
session.mount('https://', requests.adapters.HTTPAdapter(pool_connections=20, pool_maxsize=20, max_retries=3)) - 记得在任务结束时调用
session.close(),否则连接不会释放回系统 - 避免在循环里反复创建
Session——开销大;也别在整个程序只用一个Session——变成单点瓶颈
连接池溢出时怎么快速定位是哪一环的问题?
光看报错不够。先确认是不是连接池本身卡住:打印 session.adapters['https://'].poolmanager.pools.size()(需访问私有属性,仅调试用),或更稳妥地用 urllib3.util.connectionpool 日志:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
立即学习“Python免费学习笔记(深入)”;
import logging
logging.getLogger('urllib3.connectionpool').setLevel(logging.DEBUG)
日志中出现 Starting new HTTPS connection 过多,说明没复用连接;出现 Connection pool is full 则证实是 pool_maxsize 不足;若大量 Resetting dropped connection,可能是服务端主动断连,需加 keep-alive 头或缩短 timeout。
真正难的不是调参数,是分清「该限制并发」还是「该扩连接池」——前者省资源,后者治标不治本。流量突增时,信号量限流比无脑调大 pool_maxsize 更可靠。

















