异步编程核心是单线程高效轮转i/o任务,需选对框架并启用异步支持,替换同步库为异步版本,避免阻塞操作,合理使用async with和asyncio.gather。

核心是让耗时操作不卡住整个请求处理流程,尤其适用于数据库查询、HTTP调用、文件读写等I/O密集型任务。关键不在“多线程”,而在“单线程里高效轮转多个任务”。
选对框架并启用异步支持
不同框架开启异步的方式不同,不能只加async/await就完事:
-
FastAPI:直接用
async def定义路由函数,底层Starlette自动调度 -
Falcon:必须使用
falcon.asgi.App(不是falcon.App),否则async方法会被忽略 -
aiohttp:服务器应用需用
web.Application(),客户端请求必须用aiohttp.ClientSession -
Rocket(Rust):路由函数标记
async fn,依赖tokio运行时
把真正耗时的操作替换成异步版本
写了async def但内部调用的是同步库(比如requests.get或sqlite3.connect),等于白搭——它依然会阻塞事件循环。
- HTTP请求:用
aiohttp、httpx.AsyncClient,别用requests - PostgreSQL:用
asyncpg,不用psycopg2 - MySQL:用
aiomysql或asyncmy - Redis:用
aioredis或redis-py4.0+ 的Redis.from_url(..., decode_responses=True)(支持async)
避免在异步函数里混入同步阻塞代码
常见陷阱包括:
- 调用
time.sleep(1)→ 应改用await asyncio.sleep(1) - 用
json.loads()解析大字符串没问题,但若涉及磁盘读取,得用await aiofiles.open(...).read() - CPU密集运算(如图像处理、加密解密)不要放在async函数里长时间执行;可交由
loop.run_in_executor放到线程池中 - 别在
for循环里逐个await多个独立请求——应并发发起,再await asyncio.gather(...)
合理设计资源生命周期
异步上下文管理器(async with)不是装饰,而是保障资源及时释放的关键:
- 数据库连接池:用
async with pool.acquire() as conn: - HTTP会话:用
async with aiohttp.ClientSession() as session: - 文件操作:用
async with aiofiles.open(...) as f: - 手动创建的
asyncio.Task,记得在合适时机task.cancel()并await task清理











