FastAPI路由循环中使用time.sleep(1)是否会阻塞其他路由?
你的FastAPI路由阻塞问题解答
核心结论
你当前的代码不会阻塞整个FastAPI服务,但会占用单个处理线程10秒——FastAPI默认搭配的Uvicorn等ASGI服务器会维护一个线程池处理同步路由(用def定义的路由)。当这个路由的线程被time.sleep(1)卡住时,其他请求会由线程池里的空闲线程处理,所以你的测试结果是对的。
潜在风险
虽然不会堵死整个服务,但这种写法有明显的问题:
- 线程池耗尽风险:线程池的线程数量是有限的(Uvicorn默认是CPU核心数的4倍),如果同时有多个用户调用这个路由,很快就会把线程池占满,后续请求只能排队等待,导致服务整体响应变慢。
- 资源浪费:
time.sleep(1)是同步阻塞,这段时间线程完全闲置,啥也干不了,属于无效占用资源。
优化方案
把路由改成异步函数,搭配异步睡眠和异步邮件发送(或者用asyncio.to_thread包装同步邮件方法),让线程在等待时能处理其他任务:
import asyncio from fastapi import APIRouter, Depends router = APIRouter() @router.get("/send_a_bunch_of_emails") async def send_a_bunch_of_emails(db: Session = Depends(get_db)): users = get_a_bunch_of_users(db) for user in users: # 用to_thread把同步的send_email放到单独线程执行,不阻塞事件循环 await asyncio.to_thread(send_email, to=user.email) await asyncio.sleep(1) # 异步睡眠,释放事件循环处理其他请求
这样改后,事件循环可以在睡眠期间处理其他请求,线程资源利用率更高,也能避免线程池被占满的问题。
内容的提问来源于stack exchange,提问作者Glenn
相关产品推荐
相关产品推荐

