39. FastAPI 部署和执行
部署让程序持续、可观测地提供服务
本机能启动只是第一步。部署还要处理依赖复现、进程重启、HTTPS、代理、数据库迁移、日志、健康检查和回滚。先让单进程可靠运行,再按实际负载增加进程或实例。
以下默认使用第 29 篇的 app/main.py 入口;单文件练习把 app.main:app 换成 main:app。
开发与生产启动
# 开发:自动重载,只监听本机。
uv run uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
# 生产启动示例:先在交付目录同步已审核锁文件。
uv sync --locked --no-dev
uv run --no-sync uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2生产关闭 reload。不要同时使用 reload 与多 worker。0.0.0.0 只代表监听网卡,公网访问仍受网络路由、防火墙和安全组影响;浏览器用实际域名或 IP。
Uvicorn 多进程可在支持的平台上运行;启动必须使用可导入的模块路径。若在 Python 代码里调用 uvicorn.run(..., workers=...),需按要求放在 if __name__ == "__main__": 保护下。
多进程带来的实际变化
每个 worker 都有自己的内存、应用生命周期和连接池。内存字典、聊天室房间、演示后台任务状态不会自动共享。第 37、38 篇的内存状态示例必须单进程运行,或先改成数据库、Redis、可靠队列。
每进程 MySQL 最大连接数若为 15,两个 worker 就可能使用 30 个,再加迁移、队列和其他服务。worker 数量应结合 CPU、内存、I/O 和数据库上限实测,不照抄固定公式。
容器化的最小流程
在项目根目录先导出当前锁文件的运行依赖:
uv export --frozen --no-dev --no-emit-project --output-file requirements.txt创建 Dockerfile,本例针对没有额外系统依赖的纯 Python 工程:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
RUN useradd --create-home appuser
USER appuser
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"].dockerignore 排除 .git、.venv、.env、缓存和本地上传文件。构建前重新导出依赖;正式发布还应固定并维护基础镜像版本或摘要。
docker build -t fastapi-study:1.0 .
docker run --rm -p 8000:8000 --env-file .env fastapi-study:1.0镜像不内置真实密钥;生产由运行平台注入配置。非 root 用户不能随意写 /app,上传和导出应挂载具有适当权限的持久目录或使用对象存储。容器内 127.0.0.1 指当前容器,不是宿主机或另一个 MySQL 容器。
反向代理、HTTPS 与长连接
生产常见结构:客户端 → HTTPS 代理或负载均衡 → Uvicorn → 数据库。HTTPS 可在代理终止,内部网络访问按部署边界控制。
下面是 Nginx 的片段示意,不是含证书和站点配置的完整文件。map 放在 http 上下文;location 放在实际 server 中:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 放入 server 块:普通 HTTP 与 WebSocket。
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
}
# SSE 单独关闭缓冲;按实际接口路径调整。
location /chat/stream {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 300s;
}只在应用实际处于可信代理后时启用并限制转发头信任来源。公网客户端不能直接伪造真实 IP 或协议。反向代理若移除路径前缀,还要正确配置 root_path 与文档地址;不能靠随意改路由修补。
迁移、启动与回滚顺序
- 备份并确认数据库恢复方案,审核 Alembic 迁移。
- 在独立发布步骤运行迁移,避免每个 worker 同时建表或改表。
- 启动新版本,验证健康检查、登录、数据库读写和长连接。
- 逐步切流量,观察错误率、延迟、连接池和资源占用。
- 异常时回滚应用;数据库结构变更不一定能直接逆转,应设计前后版本兼容窗口。
进程由容器编排平台、systemd 或合适的服务管理器负责重启,不能长期依赖一个手工打开的终端。停止时留出优雅退出时间;WebSocket 和长流连接还需安排重连与最大持续时长。
健康与日志
存活探针回答进程是否活着;就绪探针回答能否接收业务,必要时检查关键依赖。避免每秒探针都做昂贵全表查询。日志写标准输出,包含请求 ID、路径、状态和耗时;指标至少观察错误率、延迟、数据库连接、任务积压。
练习:本机以生产命令运行,关闭进程后验证服务管理器是否恢复;容器中测试健康接口;检查 WebSocket、SSE 是否经过代理后仍能正常持续通信。