Uvicorn的--workers参数启用的是1个主进程+多个子进程的多进程模式,而非独立可调度的多实例;各子进程共享端口、内存隔离、状态不共享,崩溃后由主进程拉起但不重载配置。

uvicorn --workers 参数直接启用多进程,不是“多实例”
很多人误以为 uvicorn --workers 4 启动的是 4 个独立可调度的“实例”,其实它启动的是 1 个主进程 + 4 个子进程,全部共享同一端口、由内核用 SO_REUSEPORT 或主进程分发连接。这不是服务发现意义上的多实例,也没有独立生命周期——一个子进程崩溃,主进程会拉起新进程,但不会重新加载配置或重连数据库。
如果你需要真正可独立部署、可弹性扩缩、能跨机器调度的“多实例”,--workers 不是解法,得换架构。
用 Nginx 做反向代理实现多 uvicorn 进程间负载均衡
当你手动启动多个 uvicorn 进程(比如监听不同端口),Nginx 就成了最轻量、最可控的负载均衡层。这适合需要隔离部署、灰度发布或混合运行不同版本应用的场景。
- 每个 uvicorn 进程必须绑定不同端口,例如:
uvicorn main:app --port 8001 --workers 1、uvicorn main:app --port 8002 --workers 1 - Nginx 配置里用
upstream定义后端池,推荐加least_conn或ip_hash(如需会话粘性) - 务必设置
proxy_set_header Host $host;和proxy_set_header X-Forwarded-For $remote_addr;,否则 FastAPI 的request.url构造会出错 - 避免在多个 uvicorn 进程中使用内存缓存(如
dict或lru_cache),它们彼此不通信,数据必然不一致
为什么不能靠 PostgreSQL 实现 uvicorn 实例间任务分发
PostgreSQL 可以支撑 Heym 这类工作流系统的负载均衡,是因为 Heym 显式把任务建模为数据库行,并用 LISTEN/NOTIFY 触发唤醒。uvicorn 本身没有任务队列抽象,也不监听数据库事件——它只处理 HTTP 请求。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
想让多个 uvicorn 实例协同处理后台任务,你必须自己实现:
- 用 pg_notify 或 pg_listen 在某个实例中监听变更
- 用 asyncpg 主动轮询任务表并加行锁(SELECT ... FOR UPDATE SKIP LOCKED)
- 把耗时逻辑从 HTTP handler 中剥离,丢进独立 worker 进程(如 Celery 或自研任务循环)
- uvicorn 实例只做 API 网关,不承担执行责任
多实例下状态共享的三个现实约束
真正跨进程/跨机器的多实例部署,绕不开状态一致性问题。以下三点常被低估:
-
logging配置必须走集中式(如syslog或structlog+ Kafka),否则各实例日志时间戳和上下文无法对齐 - 如果用了
fastapi.Depends注入全局单例(如数据库连接池、Redis client),每个 uvicorn 进程都会创建自己的副本——连接数会线性增长,可能打爆 Redis 或 DB 的max_connections - HTTPS 证书不能靠 uvicorn 自己加载多份(易触发 Let’s Encrypt 频率限制),应统一由 Nginx 终止 TLS,uvicorn 只跑 HTTP 内网通信
多实例不是简单复制进程,而是把部署粒度从“一个服务”变成“一组协作节点”。关键不在怎么启动,而在怎么让它们不互相干扰、不重复做事、出问题时边界清晰。










