← 编程返回顶部

Gunicorn + Uvicorn:Python Web 服务部署

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 对比

特性WSGIASGI
主要编程模型同步支持同步与异步
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:applicationDjango ASGI 应用入口
-k指定 Worker 类型
--workersWorker 进程数量
--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 -

核心参数

参数作用
workersWorker 进程数
bind监听 IP/端口
timeoutWorker 无响应超时
graceful_timeout优雅关闭或重启的等待时间
max_requestsWorker 处理一定数量请求后重启
max_requests_jitter给重启阈值加入随机偏移
accesslogHTTP 访问日志位置
errorlog错误日志位置
loglevel日志等级
preload_app在 Master 中预加载应用
worker_tmp_dirWorker 临时文件目录

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
FastAPIUvicorn 或 Gunicorn + Uvicorn
单台 VPS + Docker ComposeGunicorn + Uvicorn 很合理
AWS ECS / 普通容器服务两种方式均可
Kubernetes可以采用单进程或少 Worker + 多 Pod
小型个人项目直接 Uvicorn 更简单
大量异步 I/OASGI + 真正的异步处理
WebSocketASGI Server + 支持 WebSocket 的应用
普通同步 DRF APIGunicorn + WSGI 也可满足需求

总结

Gunicorn 与 Uvicorn 分别解决不同层面的问题:

组件核心职责
Nginx反向代理、HTTPS、静态资源
GunicornWorker 进程管理与生命周期
UvicornASGI 协议、HTTP 处理、异步事件循环
Django / FastAPIAPI、业务逻辑、数据库访问
Celery后台异步任务处理
Docker容器运行与环境隔离
Kubernetes容器编排和横向扩容

最关键的理解是:

Gunicorn 解决进程管理问题,Uvicorn 解决 ASGI 服务运行问题,而应用本身是否真正具有异步优势,取决于业务代码及其依赖。

对于单台 VPS 上的 Django + DRF 项目,可以继续使用 Gunicorn + Uvicorn Worker。

在这一基础上,应优先关注:

  • Worker 数量和内存占用。
  • 数据库连接数量。
  • 请求超时与日志。
  • Nginx 反向代理配置。
  • 健康检查和自动重启。
  • 长时间运行任务是否需要 Celery。

参考文档