FastAPI 部署实战:使用 `--workers` 让 Uvicorn 开启多 Worker 进程,榨干多核 CPU
本文对应 FastAPI 官方部署指南中的 "Server Workers - Uvicorn with Workers" 章节(仓库内以多语言维护,含 英文原文 与 印地语译文),系统讲解在生产部署场景下如何为 FastAPI 应用启用多个 Uvicorn Worker 进程。阅读完本文,你将理解:为什么部署时需要进程复制(Replication)、如何用 fastapi run --workers 或 uvicorn --workers 一条命令启动多 Worker、如何解读启动日志中的进程 PID 层次,以及这些 Worker 与内存、重启等部署概念之间的关系。
回到部署概念:Replication 是什么
在动手之前,先回顾官方在 Deployment Concepts 章节 中列出的六条部署概念清单:
- Security(HTTPS)
- startup 时自动运行
- Restarts(崩溃后重启)
- Replication(正在运行 process 的数量)
- Memory(内存占用)
- 启动前的 prior steps(如数据库迁移)
到目前为止,官方文档中的所有教程示例,基本都通过 fastapi 命令(其底层运行 Uvicorn)只启动了单个 process 来运行应用。
但在真正把应用部署上线时,你通常需要做进程复制:同时在多台机器或同一台机器的多个核上运行多个 process,从而:
- 充分利用 CPU 的 multiple cores(多核);
- 在单个 process 的处理能力之外,handle(承接)更多的请求。
关于 "Program"(程序文件)与 "Process"(运行中的进程)的严格区别、为何同一个程序可以同时存在多个运行进程,官方在 Program and Process 小节 中有更底层的解释。简单说:代码文件本身不干活,只有被操作系统执行、占用 CPU 与内存的那个运行实体(即 process)才能处理请求;同一个程序完全可以被同时多次执行,产生多个 process。
多条进程复制路径:本节的主角是 --workers
在 Deployment Concepts 中提到,实现复制的手段不止一种:
- Uvicorn
--workers:由一个 Uvicorn process manager 监听某个 IP 与端口,再启动多个 Uvicorn worker processes; - Kubernetes 等分布式容器系统:由容器编排层监听 IP 与端口,通过多个容器实现复制(每个容器内通常只跑单个 Uvicorn process);
- 云托管服务:由云平台替你处理复制。
本篇文章聚焦第一种最朴素、也最容易理解的方式——用命令行参数 --workers 直接拉起多个 Worker 进程。它适用于你自己搭建部署体系、并愿意自己负责其余部署概念的场景。
启动 Multiple Workers:fastapi 命令
官方推荐的方式是使用 fastapi 命令(对应底层由 fastapi/cli.py 将执行委托给 fastapi_cli 中的 cli_main;同时也可通过 fastapi/main.py 用 python -m fastapi 等价调用):
$ fastapi run --workers 4 main.py
实际运行输出大致如下:
FastAPI Starting production server 🚀
Searching for package file structure from directories with
__init__.py files
Importing from /home/user/code/awesomeapp
module 🐍 main.py
code Importing the FastAPI app object from the module with the
following code:
from main import app
app Using import string: main:app
server Server started at http://0.0.0.0:8000
server Documentation at http://0.0.0.0:8000/docs
Logs:
INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO Started parent process [27365]
INFO Started server process [27368]
INFO Started server process [27369]
INFO Started server process [27370]
INFO Started server process [27367]
INFO Waiting for application startup.
INFO Waiting for application startup.
INFO Waiting for application startup.
INFO Waiting for application startup.
INFO Application startup complete.
INFO Application startup complete.
INFO Application startup complete.
INFO Application startup complete.
要点解读:
- 唯一的新参数就是
--workers 4,它指示 Uvicorn 一次性启动 4 个 worker process; fastapi run会自动做两件事:一是从模块里找到 FastAPI 的app对象(此例等价于from main import app,并使用 import stringmain:app);二是选用 Uvicorn 作为生产级 ASGI server 启动;- 默认监听
0.0.0.0:8000,交互式 API 文档地址为http://0.0.0.0:8000/docs。
为什么必须装 fastapi[standard]
注意:fastapi 这个命令行本身属于可选依赖。查看仓库中的 fastapi/cli.py,其实现是在导入 fastapi_cli.cli 失败时抛出一个明确错误,提示需要先执行:
$ pip install "fastapi[standard]"
对应的行为在 tests/test_fastapi_cli.py 中被测试覆盖(test_fastapi_cli_not_installed 断言了上述提示文案)。也就是说:标准安装的 FastAPI 会带上 Uvicorn 与 CLI 入口,但如果你的环境是精简安装,必须先补装 fastapi[standard],fastapi run 才可用。
启动 Multiple Workers:直接使用 uvicorn 命令
如果你更喜欢不经过 fastapi 封装、直接使用 Uvicorn(例如在进程管理器脚本、systemd unit 或容器 entrypoint 里),则必须显式传入 import string,告诉 Uvicorn 去哪里找 FastAPI 应用:
$ uv run uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
其中 uvicorn main:app 的含义与 from main import app 等价(main 指 main.py 模块,app 是文件中 app = FastAPI() 创建的对象)。实际运行日志形如:
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO: Started parent process [27365]
INFO: Started server process [27368]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Started server process [27369]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Started server process [27370]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Started server process [27367]
INFO: Waiting for application startup.
INFO: Application startup complete.
关于 --host 0.0.0.0 与 --port:生产服务器上监听 0.0.0.0 可让外界通过网络访问;--port 8080 可避免与默认的 8000 冲突。这些都来自 Uvicorn 的标准 CLI 参数,fastapi run 则对其做了默认封装。
解读日志中的 PID:parent process 与 worker process
上面两份日志中其实隐藏着 Uvicorn 多进程模型的核心机制——请把注意力放在每一行 PID 上:
Started parent process [27365]:27365 是 parent process(父进程) 的 PID,它扮演 process manager(进程管理器) 的角色,负责创建并监督下面的 worker;- 随后出现 4 行
Started server process [...]:27368、27369、27370、27367 是四个 worker process 各自的 PID。
它们的分工是:parent(manager)负责管理,真正跑你的 FastAPI 应用、接收请求并返回响应的,是那 4 个 worker process。这正好印证了 Deployment Concepts 中的 Multiple Processes 示例:一个 manager process 监听端口并把通信转发给多个 worker。
只有 parent 监听端口
根据 Worker Processes and Ports 小节 的解释,一个 IP 与端口的组合只能被一个 process 监听。因此多个 worker 并存时,必须由单一的管理者(parent process / process manager)负责监听端口,再将流量分发给各个 worker——这正是 --workers 模式内部所做的事情,也是它能与 Linux 端口监听约束共存的原因。
Workers 在部署概念中的定位:解决 Replication,仅部分解决 Restarts
回到开头的六条部署概念,Worker 机制主要解决其中两条:
| 部署概念 | --workers 是否覆盖 |
说明 |
|---|---|---|
| Replication(进程数量) | ✅ 主要解决 | 一条命令拉起 N 个并行 process,充分利用多核 CPU |
| Restarts | ⚠️ 部分解决 | 某个 worker 崩溃时,manager 可重新拉起,帮助你维持服务 |
| Security - HTTPS | ❌ 仍需自理 | 需要 TLS Termination Proxy 等外部组件 |
| 启动时自动运行 | ❌ 仍需自理 | 需要 systemd、Supervisor、Docker 等工具 |
| Memory | ❌ 仍需自理 | worker 之间默认不共享内存,内存开销随 worker 数成倍增加 |
| 启动前的 prior steps | ❌ 仍需自理 | 需要保证只执行一次,例如数据库迁移 |
特别提醒 Memory 维度:多进程通常不共享内存,每个 process 都拥有自己独立的一份变量与内存空间。官方在 Memory per Process 小节 中举过一个直观例子:如果你的代码加载了约 1 GB 的机器学习模型,那么启动 1 个 worker 至少占用 1 GB RAM,启动 4 个 worker 就至少需要 4 GB RAM。若服务器只有 3 GB 内存却配了 4 个 worker,就可能触发内存耗尽。因此 --workers 的数量要结合每进程内存占用与机器总 RAM 一起规划,并不存在一个通用的最优数字。
容器场景的例外:Kubernetes 通常不用 workers
本文介绍的 --workers 方案适合自行搭建部署体系的情形。但如果你使用 Docker / Kubernetes 等容器技术,官方指南建议采取另一条路径——请参考下一章 Containers 中的 FastAPI - Docker:
- 特别地,在 Kubernetes 上运行时,通常不建议使用 workers,而是每个 container 里只运行单个 Uvicorn process;
- 进程复制的职责交给 Kubernetes 本身完成:由编排层负责监听 IP 与端口,并通过多个 container(Pod)副本来实现横向扩展(参见 Replication Tools 小节 中 "Kubernetes + 每容器单 Uvicorn process" 的策略);
- 这样做的好处是:健康检查、滚动更新、崩溃重启、资源配额等都由容器平台统一管理,比在容器内部手动拉起一堆 worker 更符合平台化运维习惯。
Docker 章节还会演示如何从零编写自己的镜像,以便在容器内运行单个 Uvicorn process。
小结(Recap)
- 可以通过
fastapi run --workers 4 main.py或uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4两条命令,以--workers参数启动多个 worker process; - 多个 worker 并行运行可充分利用 multi-core CPU,承接更多并发请求;
- 启动日志中,parent process 是 process manager,后面每一行
Started server process对应一个 worker; --workers主要解决部署概念中的 Replication,并在一定程度上帮助 Restarts;- 其余概念(HTTPS、开机自启、内存规划、启动前迁移等)仍需你自行负责,或改用容器/云平台来解决;
- 如果你用的是 Docker / Kubernetes,请优先阅读 Docker 部署章节,通常应走“每个容器单进程 + 平台水平复制”的路线,而不是在容器里开一堆 worker。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00