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

FastAPI与Uvicorn多Worker异常:仅单个Worker处理后续请求

关于FastAPI+Uvicorn多Worker请求处理的疑问

我编写了一个示例FastAPI应用,包含一个延迟5秒后返回结果的端点,代码如下:

from fastapi import FastAPI
import uvicorn, os, time
app = FastAPI()

@app.get("/delayed-response")
async def read_root():
    time.sleep(5)
    return {"message": f"This is a delayed response!- {os.getpid()}"}

if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host='127.0.0.1',
        port=9090,
        reload=False,
        workers=10, #Just having 10 workers to understand the concept.
    )

我同时编写了一个脚本,向端点http://localhost:9090/delayed-response发送并行请求。

启动应用后,确认PID为9至18的10个Worker已成功启动。

当发送20个并行请求时,我观察到仅前一批请求由多个Worker并行处理,后续所有请求仅由单个Worker处理。

现提出以下疑问:

  1. 为何突发请求时,前与Worker数量相等的请求能并行处理,后续仅单个Worker处理请求?
  2. 该行为属于FastAPI还是Uvicorn的特性?

注:请将此应用视为同步应用,我了解实现并发的相关概念,但当前希望理解该现象的运行机制。

我的预期:配置10个Worker并发送30个并行请求时,第30个请求应在约15至17秒时得到响应。


问题解答

1. 后续请求仅单个Worker处理的原因

你的端点使用了time.sleep(5)这种同步阻塞操作,而Uvicorn的Worker默认基于asyncio事件循环。每个Worker内部是单线程的事件循环——当Worker处理包含同步阻塞操作的请求时,整个事件循环会被完全卡住,无法处理其他请求。

发送20个并行请求时,前10个请求会被10个Worker各自分配一个,每个Worker开始执行time.sleep(5),此时所有Worker都处于阻塞状态。后续的10个请求会被操作系统的TCP连接队列暂存,当第一个Worker完成睡眠返回响应后,它会从连接队列中取出下一个请求处理,但此时其他Worker还在阻塞中,所以后续请求会被这个空闲的Worker逐个处理,直到其他Worker陆续释放。

简言之:每个Worker一次只能处理一个同步阻塞请求,前10个Worker被占满后,后续请求只能排队等待Worker逐个释放,因此看起来是单个Worker在处理后续请求。

2. 该行为属于Uvicorn的特性

这个现象和FastAPI无关,完全由Uvicorn的Worker模型导致。FastAPI仅负责定义路由和处理逻辑,实际的请求调度、Worker管理都是Uvicorn的职责。

Uvicorn默认的UvicornWorker是单线程异步模型,遇到同步阻塞操作时会阻塞整个Worker的事件循环,无法并发处理多个请求。如果要让每个Worker能处理多个请求,可使用支持多线程的Worker(比如UvicornH11Worker配合线程池),或者将同步阻塞操作放到线程池/进程池中执行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:27:44