Python 3.12 高并发需避免阻塞事件循环、压榨I/O并发度并用对底层机制;asyncio.run()不适合长期服务,应手动管理循环或用uvloop;须组合uvloop+asyncpg+aiohttp,配合系统调优与CPU密集任务切出。

直接说结论:Python 3.12 中用 asyncio 做高并发网络 IO,关键不是“加 async”,而是避免阻塞事件循环、压榨 I/O 并发度、并用对底层机制——否则并发量卡在几千就上不去,甚至比线程池还慢。
为什么默认 asyncio.run() 在高并发下会掉链子
Python 3.12 虽然默认启用了更高效的 SelectorEventLoop,但 asyncio.run() 每次都新建并关闭事件循环,不适合长时运行的网关或服务器。高频启停会触发 GC 抖动,协程对象频繁创建/销毁也拖慢调度。
- 生产服务必须手动管理事件循环:用
asyncio.new_event_loop()创建后显式loop.run_forever(),或搭配uvloop替换默认循环 -
asyncio.run()只适合脚本级短任务;长期服务中它会掩盖RuntimeError: Event loop is closed这类资源泄漏问题 - 3.12 的
asyncio默认禁用debug=True,但上线前务必临时开启,它能捕获Task was destroyed but it is pending!这类悬空任务
uvloop + asyncpg + aiohttp 是 3.12 高并发 IO 的铁三角
原生 asyncio 在 socket 层和数据库层仍是瓶颈。3.12 下必须组合使用三者才能释放真实性能:
-
uvloop:Cython 实现的事件循环,比标准SelectorEventLoop快 40%+,且完全兼容 3.12;安装后只需在入口加import uvloop; uvloop.install() -
asyncpg:唯一支持 pipeline 查询和连接池自动复用的 PostgreSQL 异步驱动;避免用aiomysql或aiosqlite,它们在 3.12 下仍有锁竞争问题 -
aiohttp:注意必须用ClientSession复用连接,且设置connector=TCPConnector(limit=1000, limit_per_host=100),否则默认只开 100 个连接,瞬间打满端口
并发控制别只靠 asyncio.Semaphore
asyncio.Semaphore 是最常用的限流手段,但它只管“协程数量”,不管“系统资源水位”。在百万连接场景下,光靠它会触发 OSError: [Errno 24] Too many open files 或 ConnectionRefusedError。
立即学习“Python免费学习笔记(深入)”;
- 必须配合系统级调优:
ulimit -n 1048576(启动前执行),否则 Python 进程连 1024 个连接都撑不住 - HTTP 客户端要设两级限流:外层用
asyncio.Semaphore控制并发请求数,内层用aiohttp.TCPConnector的limit_per_host防止单域名打爆远端 - 对于长连接服务(如 WebSocket),要用
asyncio.wait_for()包裹每个读写操作,超时设为 30 秒以内,否则一个卡死连接会拖垮整个事件循环
CPU 密集任务必须切出事件循环
这是 3.12 下最容易被忽略的致命点:哪怕只有一行 json.loads() 或 base64.b64decode(),只要数据量大,就会让事件循环卡住超过 10ms,导致其他协程全部饿死。
- 绝对不要在协程里做解压缩、图像处理、大 JSON 解析;统一走
loop.run_in_executor(None, cpu_bound_func, *args) - 3.12 的
concurrent.futures.ProcessPoolExecutor已支持initializer参数,可提前加载模型或配置,避免每次 fork 初始化开销 - 如果必须解析大响应体,用
response.content.iter_chunked(8192)分块读取 + 流式 JSON 解析(如ijson),而不是等整个 body 下载完再await response.text()
真正难的不是写 async def,而是判断哪一行代码会把事件循环钉住——3.12 的 asyncio 不再容忍任何隐式同步操作,连 time.time() 都建议换成 loop.time() 才够精确。


















