Uvicorn --workers 自0.29版起已生产就绪,但行为与Gunicorn不同:各worker独立fork、不共享内存或事件循环,需重配端口、超时、日志等参数,并显式设置--graceful-timeout和--timeout-graceful-shutdown以保障优雅退出。

Uvicorn --workers 在 2026 年已真正可用,但配置逻辑变了
Uvicorn 从 0.29 版起(2025 年中)开始原生支持健壮的多进程管理,--workers 不再是“实验性开关”,而是生产就绪功能。但它的行为和 Gunicorn 的 --workers 有本质区别:Uvicorn 的 worker 是 fork 后独立运行的 ASGI 实例,不共享内存、不共用事件循环,也不依赖 master 进程做统一调度——它自己用 os.fork() + 信号监听实现进程生命周期管理。
这意味着你不能照搬 Gunicorn 的配置项。比如:
-
--preload在 Uvicorn 中不存在,应用模块会在每个 worker 启动时单独导入 -
--max-requests和--max-requests-jitter是 Gunicorn 特有机制,Uvicorn 没有等价参数;靠重启 worker 防内存泄漏?得靠外部进程管理器(如 systemd)或自定义 healthcheck + 优雅退出逻辑 -
--worker-class在 Uvicorn 单独使用时完全无效,因为 worker 就是 Uvicorn 自身
端口绑定、超时、日志这些基础项必须重配
Gunicorn 配置里常见的 bind、timeout、accesslog 等,在 Uvicorn 中对应的是不同参数名和语义。直接沿用旧配置会导致启动失败或行为异常。
-
bind = "127.0.0.1:8000"→ 改为--host 127.0.0.1 --port 8000,且不支持 Unix socket 路径写法(如unix:/tmp/app.sock),要用--uds /tmp/app.sock -
timeout = 120→ 对应--timeout-keep-alive 5(HTTP keep-alive 超时)和--limit-concurrency 100(并发连接上限),但没有“请求处理超时”硬限制——那是业务层该管的事 - Gunicorn 的
accesslog/errorlog→ Uvicorn 只有--log-level info和--access-log(布尔开关),日志输出到 stdout/stderr,需靠容器或 systemd 拦截落盘
别忽略信号处理和优雅退出的差异
Gunicorn 收到 SIGTERM 会通知所有 worker 逐个完成当前请求再退出;Uvicorn 默认收到 SIGTERM 后立即关闭监听套接字,正在处理的请求可能被中断(尤其是长轮询或流式响应)。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
- 必须显式加
--graceful-timeout 30(默认为 0),它控制从收到信号到强制 kill 的缓冲时间 - 还需配合
--timeout-graceful-shutdown 10(Uvicorn 0.30+ 新增),确保 worker 在 grace period 内有机会 finish 当前 task - 如果你用 systemd,
Restart=on-failure仍有效,但别设RestartSec=0,否则频繁崩溃时可能触发系统级限频
WebSocket 和长连接场景下,Gunicorn 的“假稳定”消失了
很多团队之前用 Gunicorn + UvicornWorker,是因为 Gunicorn 的 master 进程能兜底回收卡死的 worker。但实际中,ASGI worker 卡在 WebSocket await websocket.receive_text() 时,Gunicorn 并不会感知——它只看进程是否存活,不看协程是否卡住。
切换到纯 Uvicorn 后,这个问题反而更透明了:
- Uvicorn 本身不提供“worker 健康探测”,但你可以用
/health接口 + 外部探针(如 Kubernetes liveness probe)判断进程是否可响应 - 真正的解法是业务层加 timeout:比如
await asyncio.wait_for(websocket.receive_text(), timeout=30) - 如果依赖 Gunicorn 的“自动踢掉无响应 worker”错觉,现在得靠
--limit-max-requests(按请求数重启)或外部监控脚本补位
最易被忽略的一点:Uvicorn 的 --workers 模式下,每个 worker 独立监听端口(通过 SO_REUSEPORT),但 app.state、内存缓存、定时任务等完全不共享——以前靠 Gunicorn master 协调的单例逻辑,现在必须改造成 Redis 或数据库-backed。

















