aiohttp的异步性能需精细调参:tcpconnector须设limit(如500)和limit_per_host(50–100)、keepalive_timeout=30;clientsession必须复用而非新建;并发控制用semaphore+retry机制;禁用同步调用如time.sleep()。

aiohttp 的异步性能不是“开箱即用”的,不调参、不复用、不限流,跑出来的并发数越高,越容易触发连接耗尽、服务端限频或客户端内存暴涨。真正能压到 1000+ 并发且稳定运行的,靠的是对连接池、会话生命周期和错误恢复的精细控制。
如何配置 TCPConnector 避免文件描述符耗尽
aiohttp.TCPConnector 是连接层的阀门,不设限就等于没限。Linux 默认单进程最多打开 1024 个文件描述符,而每个 TCP 连接至少占一个——limit=1000 看似合理,但若没配 limit_per_host,所有请求打向同一个域名,可能瞬间被目标服务端拒绝(如 Cloudflare 503 或 Nginx 429)。
-
limit设为 1000 是上限,但建议按实际并发需求下调(例如 500),留出系统缓冲 -
limit_per_host必须设(推荐 50–100),否则单域名连接堆积会触发服务端熔断 -
keepalive_timeout=30要显式设置,否则默认 15 秒太短,频繁重连增加握手开销 -
force_close=False(默认值)必须保持,设为True会禁用连接复用,性能直接打七折
为什么 ClientSession 必须复用而非每次新建
每次async with aiohttp.ClientSession() 都会重建连接池、DNS 缓存、SSL 上下文——这些初始化成本远高于单次请求本身。实测 1000 次请求中若每次新建 session,内存峰值比复用高 3.2 倍,耗时多出 40%。
- session 应作为长生命周期对象,在整个应用或任务批次中复用
- 若需不同 headers / timeout / connector,用
session.clone(),不要新建 - 多线程场景下禁止跨线程传递 session;asyncio 场景下确保 session 与 event loop 同生命周期
- 用完后显式调用
await session.close(),否则连接池不会释放,下次 run 可能报RuntimeError: Session is closed
如何用 Semaphore + retry 实现可控的失败恢复
asyncio.gather 默认是“全成功才返回”,任一请求失败(超时、网络中断、HTTP 5xx)就会中断整个 batch。真实场景中,应允许部分失败 + 指数退避重试,同时防止失败请求反复冲击服务端。
- 用
asyncio.Semaphore(100)控制并发数,比单纯靠 connector 更灵活(可动态调整) - 每个请求包装成带重试的协程:捕获
aiohttp.ClientError和asyncio.TimeoutError,最多重试 3 次,间隔 0.5 → 1.0 → 2.0 秒 -
return_exceptions=True必须传给gather,否则一个异常导致整个任务集崩溃 - 对 HTTP 状态码做分级处理:
response.status in (429, 503)触发退避,404直接丢弃不重试
哪些操作会无声无息地拖垮异步性能
最隐蔽的坑不是写错语法,而是混入同步调用——它们不会报错,但会让整个 event loop 卡住几毫秒甚至几秒。- 绝对禁止在协程里调用
time.sleep()、requests.get()、json.load()(大文件)、open().read() -
response.json()是异步安全的,但response.text()在响应体极大时可能阻塞(内部用bytes.decode()),建议改用response.content.read()流式处理 - 日志写入若用标准
logging.info(),底层是同步 IO,高并发下会成为瓶颈;应改用aiologger或把日志写入队列由单独协程刷盘 - DNS 解析默认走线程池,若目标域名多且不稳定,应启用
aiodns(pip install aiodns),并传resolver=aiohttp.AsyncResolver()给 connector
真正卡在 200 并发上不去的,90% 不是代码逻辑问题,而是 connector 参数没调、session 没复用、或者某处偷偷调了 time.sleep(1)。先盯住这三处,比优化算法更立竿见影。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











