You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI与Uvicorn的CPU核心利用机制及相关技术疑问

FastAPI & Uvicorn 运行机制常见问题解答

问题一:若所有端点均使用async def,是否意味着工作线程实际未发挥作用?

不是完全闲置。Uvicorn的线程池核心作用是承载同步阻塞任务,但如果你的异步端点里主动调用了同步阻塞函数(比如通过asyncio.to_thread(),或者不小心在async def里写了阻塞逻辑),线程池还是会被用来处理这些逻辑,避免阻塞整个事件循环。要是所有异步端点全是纯异步IO操作(比如async数据库驱动、async HTTP请求),那线程池确实没什么负载,但Uvicorn仍会维持这个池,只是多数时候处于闲置状态。

问题二:若Uvicorn确实使用线程,Python的GIL是否会阻止其利用多核实现多线程并发?若确实如此,为何推荐将线程数与核心数绑定?

首先要明确:你提到的「2×CPU核心数+1」是Uvicorn的worker进程数,不是线程池的线程数,很多人会混淆这两个概念。

  • GIL确实会限制单个Python进程内的多线程无法利用多核,但Uvicorn的worker是独立的进程,每个worker都有自己的GIL,多worker进程可以充分利用多核CPU。
  • 线程池的线程是每个worker进程内部的,用来处理同步任务。这些线程受GIL限制,同一时间只有一个线程在执行Python字节码,但对于IO密集型的同步任务(比如数据库查询、文件读写),线程会在IO等待时释放GIL,让其他线程得以运行,所以线程池依然能提升并发能力。
  • 推荐worker数和核心数绑定,是因为这个经验值能平衡CPU密集型和IO密集型任务的需求:CPU密集型任务靠多进程利用多核,IO密集型任务靠多进程提升并发上限。

问题三:在同步端点和异步端点两种情况下,任务的执行顺序是如何确定的?

异步端点

任务由Uvicorn的事件循环调度,遵循协程调度规则:事件循环会持续切换执行就绪的协程,当某个协程遇到IO等待(比如等待数据库响应)时,就暂停它,转而执行另一个就绪的协程。任务的执行顺序不是严格的请求到达顺序,而是取决于哪个协程先进入就绪状态(比如IO操作完成的先后)。

同步端点

FastAPI会把同步函数提交到Uvicorn的线程池执行,线程池的调度由concurrent.futures.ThreadPoolExecutor管理:

  • 任务默认按**FIFO(先进先出)**的顺序进入等待队列;
  • 若有空闲线程,先到达的任务会先执行;若所有线程都处于忙碌状态,任务会排队等待,直到有线程空闲后按队列顺序执行;
  • 对于CPU密集型的同步任务,受GIL限制,同一进程内的线程会串行执行;但如果是IO密集型任务,线程在等待IO时会释放GIL,让其他线程有机会运行。

内容的提问来源于stack exchange,提问作者Dannynis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:55:22