Gunicorn + Uvicorn 是 Python Web 项目常见的生产部署组合。
其中:
- Gunicorn:负责进程管理、Worker 生命周期、信号处理和进程级并发。
- Uvicorn:负责运行 ASGI 应用,处理 HTTP、异步 I/O 及 ASGI 协议通信。
- Django / FastAPI:负责路由、业务逻辑、数据库访问等应用功能。
- Nginx:通常作为反向代理,负责 HTTPS、静态资源、请求转发等。
典型架构:
Client
↓
Nginx (Reverse Proxy)
↓
Gunicorn (Master Process)
│
├── Uvicorn Worker 1 ──→ Django ASGI
├── Uvicorn Worker 2 ──→ Django ASGI
├── Uvicorn Worker 3 ──→ Django ASGI
└── Uvicorn Worker 4 ──→ Django ASGI
Gunicorn 管理 Worker 进程,而实际的 ASGI 请求处理由 Worker 中运行的 Uvicorn 完成。
1. WSGI 与 ASGI
WSGI
WSGI(Web Server Gateway Interface)是 Python Web 服务器与应用程序之间的标准接口。
传统 Django 通常使用 WSGI:
Client
↓
Nginx
↓
Gunicorn (WSGI Worker)
↓
Django WSGI Application
启动:
gunicorn config.wsgi:application
WSGI 主要围绕同步请求响应模型设计。
ASGI
ASGI(Asynchronous Server Gateway Interface)是支持异步通信的接口标准。
ASGI 支持:
- HTTP 请求。
- 异步处理。
- WebSocket 协议接口。
- 长连接场景。
- ASGI Lifespan 等协议扩展。
典型架构:
Client
↓
Nginx
↓
Uvicorn (ASGI Server)
↓
Django / FastAPI
启动:
uvicorn config.asgi:application
WSGI 与 ASGI 对比
| 特性 | WSGI | ASGI |
|---|---|---|
| 主要编程模型 | 同步 | 支持同步与异步 |
| HTTP | 支持 | 支持 |
| WebSocket | 不原生支持 | 协议层支持 |
| 长连接 | 有一定限制 | 更适合 |
| async/await | 不原生支持 | 原生支持 |
| Django | 支持 | 支持 |
| FastAPI | 通常不使用 | 原生 ASGI |
注意:ASGI 服务器支持 WebSocket,不代表 Django 自带的 ASGI 应用就能直接处理 WebSocket。
Django 项目通常需要 Django Channels 或其他 ASGI 路由组件来实现 WebSocket 服务。
2. Uvicorn
Uvicorn 是 Python ASGI Server。
主要负责:
- 接收 HTTP 连接。
- 解析 HTTP 请求。
- 调用 ASGI Application。
- 管理异步事件循环。
- 处理 ASGI HTTP/WebSocket 协议。
- 向客户端发送 HTTP 响应。
工作原理
HTTP Request
↓
Uvicorn
↓
ASGI Scope / Receive / Send
↓
Django ASGI Application
↓
View / Business Logic
↓
ASGI Response
↓
Uvicorn
↓
HTTP Response
Uvicorn 使用事件循环处理异步任务,可以在等待网络或其他异步 I/O 时继续处理其他请求。
开发环境启动
uvicorn config.asgi:application --reload
--reload 会监控代码变化,并自动重启应用,主要用于开发环境。
生产环境启动
uvicorn config.asgi:application \
--host 0.0.0.0 \
--port 8000 \
--workers 2
--workers 可以启动多个 Uvicorn Worker 进程。
注意:--reload 和 --workers 不能同时使用。
因此,Uvicorn 不只是单进程服务器,它本身也具有一定的多进程管理能力。
3. Gunicorn
Gunicorn(Green Unicorn)是 Python WSGI HTTP Server,同时提供成熟的进程管理能力。
使用兼容的 Worker 类型时,也可以通过 Gunicorn 管理 ASGI Server。
主要功能:
- 启动多个 Worker 进程。
- 监控 Worker 状态。
- Worker 崩溃后自动重启。
- 优雅关闭与重启。
- Unix 信号处理。
- 请求超时与 Worker 健康监测。
- 日志管理。
- 控制 Worker 最大请求数量。
Master / Worker 模型
Gunicorn Master
│
├── Worker 1
├── Worker 2
├── Worker 3
└── Worker 4
Master 负责管理进程。
Worker 负责处理实际请求。
不同 Worker 类型有不同的并发模型,例如:
- sync:同步 Worker。
- gthread:线程 Worker。
- gevent:协作式并发 Worker。
- UvicornWorker:ASGI Worker。
Gunicorn 本身并不决定应用一定是同步还是异步,具体取决于使用的 Worker 类型。
4. Gunicorn + Uvicorn Worker
对于 Django ASGI 应用:
Gunicorn Master
│
├── Uvicorn Worker 1
├── Uvicorn Worker 2
├── Uvicorn Worker 3
└── Uvicorn Worker 4
每个 Uvicorn Worker 是独立的操作系统进程,运行自己的事件循环和 ASGI 应用实例。
安装
pip install gunicorn uvicorn uvicorn-worker
启动
gunicorn config.asgi:application \
-k uvicorn_worker.UvicornWorker \
--workers 4 \
--bind 0.0.0.0:8000
参数解释:
| 参数 | 作用 |
|---|---|
config.asgi:application | Django ASGI 应用入口 |
-k | 指定 Worker 类型 |
--workers | Worker 进程数量 |
--bind | 监听地址和端口 |
uvicorn.workers 的弃用
旧写法:
gunicorn config.asgi:application \
-k uvicorn.workers.UvicornWorker
uvicorn.workers 已经被 Uvicorn 官方弃用。
推荐使用独立的 uvicorn-worker 包:
gunicorn config.asgi:application \
-k uvicorn_worker.UvicornWorker
这样可以降低对已弃用模块的依赖。
5. 同步与异步并发模型
同步 Worker
传统 Gunicorn sync Worker 通常一次只处理一个请求。
Worker 1 → Request A
Worker 2 → Request B
Worker 3 → Request C
如果 Request A 正在执行耗时的同步 I/O,负责该请求的 Worker 可能无法同时处理其他请求。
异步 Worker
Uvicorn 使用事件循环,异步任务在等待 I/O 时可以让出执行权。
Uvicorn Worker
│
├── Request A → await DB
├── Request B → await HTTP
└── Request C → Processing
一个进程可以在适当的条件下并发处理多个请求。
但需要区分:
- 并发(Concurrency):多个任务在时间上交替推进。
- 并行(Parallelism):多个任务在同一时刻真正执行。
异步主要提升 I/O 等待场景的并发能力,并不自动加速 CPU 密集型计算。
CPU 密集型与 I/O 密集型
| 类型 | 示例 | 常见优化方式 |
|---|---|---|
| CPU 密集型 | 图像处理、大量 Python 计算 | 多进程、任务队列、专门计算服务 |
| I/O 密集型 | HTTP 请求、数据库等待 | 异步 I/O、适当的并发 |
| 混合型 | 数据处理 + 网络调用 | 根据瓶颈组合优化 |
例如:
async def get_data():
response = await async_client.get(
"https://example.com"
)
return response.json()
如果 HTTP Client 支持真正的异步 I/O,那么等待网络响应时,事件循环可以继续处理其他任务。
但是:
async def get_data():
response = requests.get(
"https://example.com"
)
return response.json()
这里的 requests.get() 是同步阻塞调用,可能阻塞事件循环。
因此,将函数声明为 async def 并不意味着其中的操作自动变成非阻塞操作。
6. Django ASGI 与异步支持
Django 支持同步 View 和异步 View。
同步 View
def get_data(request):
result = calculate_data()
return JsonResponse(result)
异步 View
async def get_data(request):
result = await fetch_remote_data()
return JsonResponse(result)
但 Django 通过 ASGI 运行时,同步 View 仍然需要通过同步执行机制运行,通常涉及线程适配。
Django ORM
Django 提供部分异步 ORM 方法:
user = await User.objects.aget(id=1)
以及:
async for user in User.objects.all():
print(user.username)
但 Django ORM 并非所有功能都有完整的异步支持。
特别是事务操作以及某些数据库连接管理行为,需要额外注意。
DRF 的异步支持
标准 DRF APIView、GenericAPIView 的使用方式主要围绕同步处理设计。
不能仅仅将:
def get(self, request):
...
改成:
async def get(self, request):
...
就假设完整的 DRF 请求处理链路已经支持异步。
如果需要异步 API,应根据 DRF 版本、扩展库和具体视图实现确认兼容性。
对于普通 Django REST API,使用同步 View 配合 ASGI Server 是可以接受的部署方式。
但这并不代表同步请求能直接获得原生异步 View 的全部并发优势。
7. Gunicorn 常用配置
典型启动命令:
gunicorn config.asgi:application \
-k uvicorn_worker.UvicornWorker \
--workers 2 \
--bind 0.0.0.0:8000 \
--timeout 60 \
--graceful-timeout 30 \
--max-requests 1000 \
--max-requests-jitter 100 \
--access-logfile - \
--error-logfile -
核心参数
| 参数 | 作用 |
|---|---|
workers | Worker 进程数 |
bind | 监听 IP/端口 |
timeout | Worker 无响应超时 |
graceful_timeout | 优雅关闭或重启的等待时间 |
max_requests | Worker 处理一定数量请求后重启 |
max_requests_jitter | 给重启阈值加入随机偏移 |
accesslog | HTTP 访问日志位置 |
errorlog | 错误日志位置 |
loglevel | 日志等级 |
preload_app | 在 Master 中预加载应用 |
worker_tmp_dir | Worker 临时文件目录 |
timeout 与 graceful_timeout
timeout:
--timeout 60
主要表示 Worker 在超过指定时间没有正常响应 Master 的健康检测时,可能被终止并重启。
对于异步 Worker,它不等同于单个 HTTP 请求必须在 60 秒内完成。
graceful_timeout:
--graceful-timeout 30
表示 Worker 收到优雅重启或关闭指令后,允许其完成现有工作的等待时间。
超过规定时间仍未退出的 Worker 可能被强制终止。
max_requests
--max-requests 1000
表示 Worker 在处理一定数量的请求后自动重启。
主要用于缓解潜在的内存泄漏影响。
推荐搭配:
--max-requests-jitter 100
防止多个 Worker 在相近时间同时重启。
注意:这是可选的防御措施,不是所有应用都必须启用,也不能代替修复实际内存泄漏。
8. Worker 数量与性能
Gunicorn 可以利用多个进程提高多核 CPU 的使用能力。
CPU Core 1 ← Worker 1
CPU Core 2 ← Worker 2
CPU Core 3 ← Worker 3
CPU Core 4 ← Worker 4
但这只是示意,实际进程由操作系统调度,不会永久绑定到某个 CPU Core。
Worker 数量的影响
增加 Worker:
- 可以利用更多 CPU 资源。
- 可以提高进程级并发能力。
- 增加内存消耗。
- 可能增加数据库连接数量。
- 可能提高进程调度成本。
Worker 数量不是越多越好。
实际需要根据:
CPU
RAM
平均请求耗时
同步 / 异步比例
数据库连接数
外部 I/O
请求并发量
进行调整。
Worker 与数据库连接
多个 Worker 具有独立的进程内状态和数据库连接管理机制。
Worker 1 → Database Connections
Worker 2 → Database Connections
Worker 3 → Database Connections
Worker 4 → Database Connections
需要注意:
- Django 默认不提供通用的进程内数据库连接池。
- 数据库连接的创建、关闭和复用受到 Django 配置以及所使用的数据库驱动影响。
- 多进程部署可能增加数据库最大连接数的压力。
- 额外的线程、后台任务以及数据库连接池也会影响连接总量。
对于 Django 异步模式,应特别关注持久连接配置及外部连接池的使用方式。
9. Nginx + Gunicorn + Uvicorn
典型部署架构:
Internet
↓
Cloudflare(可选)
↓
Nginx
│
├── HTTPS / TLS
├── Static Assets
├── Reverse Proxy
├── gzip / Brotli
└── Cache-Control
↓
Gunicorn Master
↓
Uvicorn Workers
↓
Django ASGI
↓
PostgreSQL
Nginx 示例
server {
listen 80;
location / {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
}
}
这里假设 backend 是 Docker Compose 中的服务名。
HTTPS 可以由另一个 Nginx Server Block 处理。
如果需要 WebSocket 代理,还需要正确配置相关 Upgrade 和 Connection Header;具体写法取决于 Nginx 版本及部署方式。
代理 Header 与安全
Uvicorn 和 Django 都需要正确识别原始请求的协议、Host 和客户端 IP。
但是不能无条件信任客户端提供的:
X-Forwarded-For
X-Forwarded-Proto
Forwarded
这些 Header 应由可信反向代理设置,并正确限定可信代理范围。
否则可能造成客户端 IP 伪造或 HTTPS 判断错误等问题。
10. Docker Compose 部署
可以在 Django Dockerfile 中安装依赖:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD [
"gunicorn",
"config.asgi:application",
"-k",
"uvicorn_worker.UvicornWorker",
"--workers",
"2",
"--bind",
"0.0.0.0:8000",
"--access-logfile",
"-",
"--error-logfile",
"-"
]
需要确保 requirements.txt 包含:
Django
gunicorn
uvicorn
uvicorn-worker
以及项目实际使用的其他依赖。
Compose 示例
services:
backend:
build: ./backend
expose:
- "8000"
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
depends_on:
- backend
这里只展示容器间请求转发相关配置。
实际项目还需要配置:
- 环境变量。
- 数据库。
- Volume。
- Nginx 配置文件。
- TLS 证书。
- Health Check。
- Migration 执行流程。
Docker 中的日志
建议将访问日志和错误日志写入 stdout/stderr。
Gunicorn:
--access-logfile -
--error-logfile -
这样 Docker 可以直接收集日志:
docker compose logs -f backend
对于容器化部署,通常不需要让应用自己维护复杂的本地日志文件轮转机制。
11. Gunicorn + Uvicorn 与直接 Uvicorn
Gunicorn + Uvicorn
Container
↓
Gunicorn Master
↓
Multiple Uvicorn Workers
↓
Django
优点:
- 成熟的进程管理。
- 多进程运行。
- Worker 自动重启。
- 优雅重启和信号管理。
- 丰富的 Worker 生命周期参数。
缺点:
- 进程层级更多。
- 配置相对复杂。
- 需要同时维护 Gunicorn 和 Uvicorn Worker 相关依赖。
- 需要关注 Worker 进程数量与资源限制。
直接 Uvicorn
Container
↓
Uvicorn
↓
Django
启动:
uvicorn config.asgi:application \
--host 0.0.0.0 \
--port 8000
优点:
- 结构简单。
- 配置较少。
- 少一层进程管理抽象。
- 适合通过容器平台实现进程重启与横向扩容。
缺点:
- 某些进程管理功能不如 Gunicorn 丰富。
- 如果只运行一个 Worker,只能利用单个进程的执行能力。
不过 Uvicorn 也支持:
uvicorn config.asgi:application --workers 4
因此不能简单认为直接使用 Uvicorn 就只能运行单进程。
12. Docker / Kubernetes 部署策略
单台 VPS + Docker Compose
VPS
↓
Docker Compose
↓
Gunicorn Master
↓
2–4 Uvicorn Workers
↓
Django
适合通过一个容器管理多个进程。
对于单机服务,Gunicorn + Uvicorn 是合理的方案。
Kubernetes
Kubernetes 可以通过多个 Pod 实现横向扩容:
Load Balancer
↓
Kubernetes Service
│
├── Pod 1 → Uvicorn
├── Pod 2 → Uvicorn
├── Pod 3 → Uvicorn
└── Pod 4 → Uvicorn
Kubernetes 主要负责:
- Pod 调度。
- 容器健康检查。
- 故障后重新创建 Pod。
- 负载分配。
- 横向扩容。
因此,在 Kubernetes 中可以考虑每个 Pod 使用一个 Uvicorn 进程,再通过增加 Pod 数量扩容。
但 Kubernetes 并不要求每个 Pod 只能运行一个 Worker。
实际选择需要综合考虑:
- Pod 资源限制。
- 应用启动时间。
- 数据库连接数。
- 内存使用。
- 自动扩容策略。
- 流量与故障恢复需求。
13. Gunicorn 常见问题
Q1:Gunicorn 和 Uvicorn 是否必须一起使用?
不必须。
可以选择:
Gunicorn + WSGI
Uvicorn + ASGI
Gunicorn + Uvicorn Worker + ASGI
具体取决于框架、协议和部署需要。
Q2:ASGI 是否一定比 WSGI 快?
不一定。
ASGI 在高并发 I/O 等待场景下可能更有优势。
但如果主要业务是同步 Django ORM、同步 DRF View 或 CPU 密集型处理,改用 ASGI 并不保证性能提升。
应该通过实际负载测试判断。
Q3:使用 Gunicorn 能不能实现真正多核并行?
可以通过多个 Worker 进程实现。
但多个 Worker 会增加内存和数据库连接开销。
Q4:是否应该把 Worker 数量设为 CPU 核数的两倍?
不应该机械套用固定公式。
Worker 数量需要结合实际请求耗时、内存、CPU、I/O 比例和数据库压力测试。
Q5:是否需要使用 Celery?
Gunicorn 和 Uvicorn 主要处理 Web 请求。
Celery 等任务队列用于执行不需要阻塞 HTTP 请求的后台任务。
例如:
Client
↓
Django API
↓
Celery Queue
↓
Celery Worker
↓
Image Processing / Long-running Job
因此 Gunicorn Worker 不是 Celery Worker。
对于耗时任务,不能单纯依靠增加 Gunicorn Worker 数量解决问题。
14. 部署方案选择
| 场景 | 常见选择 |
|---|---|
| 传统同步 Django 应用 | Gunicorn + WSGI |
| Django ASGI 应用 | Uvicorn 或 Gunicorn + Uvicorn |
| FastAPI | Uvicorn 或 Gunicorn + Uvicorn |
| 单台 VPS + Docker Compose | Gunicorn + Uvicorn 很合理 |
| AWS ECS / 普通容器服务 | 两种方式均可 |
| Kubernetes | 可以采用单进程或少 Worker + 多 Pod |
| 小型个人项目 | 直接 Uvicorn 更简单 |
| 大量异步 I/O | ASGI + 真正的异步处理 |
| WebSocket | ASGI Server + 支持 WebSocket 的应用 |
| 普通同步 DRF API | Gunicorn + WSGI 也可满足需求 |
总结
Gunicorn 与 Uvicorn 分别解决不同层面的问题:
| 组件 | 核心职责 |
|---|---|
| Nginx | 反向代理、HTTPS、静态资源 |
| Gunicorn | Worker 进程管理与生命周期 |
| Uvicorn | ASGI 协议、HTTP 处理、异步事件循环 |
| Django / FastAPI | API、业务逻辑、数据库访问 |
| Celery | 后台异步任务处理 |
| Docker | 容器运行与环境隔离 |
| Kubernetes | 容器编排和横向扩容 |
最关键的理解是:
Gunicorn 解决进程管理问题,Uvicorn 解决 ASGI 服务运行问题,而应用本身是否真正具有异步优势,取决于业务代码及其依赖。
对于单台 VPS 上的 Django + DRF 项目,可以继续使用 Gunicorn + Uvicorn Worker。
在这一基础上,应优先关注:
- Worker 数量和内存占用。
- 数据库连接数量。
- 请求超时与日志。
- Nginx 反向代理配置。
- 健康检查和自动重启。
- 长时间运行任务是否需要 Celery。