asyncio是单线程高效调度IO等待任务的机制,通过event loop实现协作式并发,需用await、gather或create_task显式并发,避免同步阻塞操作,结合连接池、超时控制与资源限制构建高并发服务。

Python异步IO(asyncio)不是“多线程替代品”,也不是“让单核变多核”的魔法——它是用单线程高效调度大量IO等待任务的机制。核心在于:当一个任务在等网络响应、磁盘读写或数据库返回时,不阻塞整个线程,而是立刻切去执行另一个就绪的任务。
async/await 是协作式调度,不是自动并行
async 函数不会自己并发运行;必须由事件循环(event loop)统一管理。你写 async def fetch(url):,只是定义了一个可挂起的协程对象,真正执行靠 await fetch(url) 或 asyncio.create_task() 注册进循环。
- 直接调用 fetch("https://a.com") 不会发请求,只返回一个 coroutine 对象
- await 是“让出控制权”的信号:当前协程暂停,把CPU交还给事件循环,等IO就绪再唤醒
- 多个 await 串行写 = 依次等待,毫无并发优势;要用 asyncio.gather() 或 create_task() 显式并发启动
高并发的关键不在“开多少协程”,而在“减少阻塞点”
协程数量可以轻松上万,但性能瓶颈常来自:同步库混用、CPU密集型操作未释放、事件循环被意外阻塞。
- 避免在 async 函数里调用 time.sleep()、requests.get()、json.loads()(大文件)等同步阻塞操作
- CPU密集任务(如图像处理、加密计算)要交给 asyncio.to_thread()(3.9+)或 loop.run_in_executor() 脱离事件循环执行
- 使用异步生态库:aiohttp 替 requests、aiomysql 替 PyMySQL、aioredis 替 redis-py
典型高并发服务结构:连接池 + 任务队列 + 超时控制
真实场景中,并发不是无节制 launch_task,而是有节制地调度资源。
立即学习“Python免费学习笔记(深入)”;
- HTTP 客户端用 aiohttp.TCPConnector(limit=100) 控制最大并发连接数,防打爆服务端
- 数据库访问搭配 asyncpg.Pool 或 aiomysql.create_pool() 复用连接,避免频繁建连开销
- 对不可控外部依赖(如第三方API),用 asyncio.wait_for(task, timeout=5.0) 主动中断慢请求,保障整体响应性
- 批量任务可用 asyncio.Semaphore(10) 限制同时执行数,防止内存或句柄耗尽
调试和监控不能只看 CPU,要盯住事件循环延迟和任务堆积
asyncio 程序卡顿,往往不是 CPU 满了,而是事件循环被拖慢,或协程长时间没被调度。
- 启用 asyncio.get_event_loop().set_debug(True) 可捕获慢回调、未 await 的协程、超长运行任务
- 用 asyncio.all_tasks() 查看当前待执行协程数量,异常增长说明某处逻辑未及时 await 或异常退出
- 监控 loop.time() - loop._last_idle(需 patch)或使用 aiomonitor 工具观察循环延迟(latency)是否持续升高
异步IO的价值,在于用更少系统资源支撑更高吞吐的IO密集型负载。它不降低单次请求延迟,但显著提升单位时间完成请求数。设计时始终问一句:这个操作,是真正在等外部设备,还是在原地空转?前者适合 async,后者该优化逻辑或换线程。










