跳到主要内容

部署与运维

问题

Python Web 应用如何部署到生产环境?Gunicorn、uWSGI、Uvicorn 怎么选?

答案

部署架构

Gunicorn 配置

gunicorn.conf.py
import multiprocessing

# Worker 数量 = 2 * CPU核心 + 1
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker" # 异步 Worker
bind = "0.0.0.0:8000"
timeout = 120
keepalive = 5
max_requests = 1000 # 处理 N 个请求后重启 Worker(防内存泄漏)
max_requests_jitter = 100 # 随机抖动,避免同时重启
preload_app = True # 预加载应用(fork 后共享内存)
accesslog = "-"
errorlog = "-"
loglevel = "info"
gunicorn app:app -c gunicorn.conf.py

Docker 部署

Dockerfile
# 多阶段构建
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY . .

# 非 root 用户
RUN useradd -m appuser
USER appuser

EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=5s \
CMD curl -f http://localhost:8000/health || exit 1

CMD ["gunicorn", "app:app", "-c", "gunicorn.conf.py"]
docker-compose.yml
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379/0
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped

db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 5s

redis:
image: redis:7-alpine

volumes:
pgdata:

Nginx 反向代理

nginx.conf
upstream app {
server 127.0.0.1:8000;
}

server {
listen 80;
server_name example.com;

location / {
proxy_pass http://app;
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;
}

location /static/ {
alias /app/static/;
expires 30d;
}
}

常见面试问题

Q1: Gunicorn vs Uvicorn vs uWSGI?

答案

服务器类型适用
GunicornWSGIDjango、Flask
UvicornASGIFastAPI、Starlette
Gunicorn + Uvicorn WorkerASGIFastAPI 生产部署(推荐)
uWSGIWSGIDjango(功能多但配置复杂)

Q2: Worker 数量怎么定?

答案

  • CPU 密集workers = CPU核心数 + 1
  • IO 密集workers = CPU核心数 * 2 + 1
  • 异步框架:可以用更少 Worker(async 本身有并发能力)

Q3: 如何实现零停机部署?

答案

  1. Gunicorn 信号kill -USR2 <pid> 优雅重启
  2. Blue-Green 部署:两套环境切换
  3. Rolling Update:K8s 滚动更新
# Gunicorn 优雅重启
kill -HUP $(cat gunicorn.pid) # 重新加载配置
kill -USR2 $(cat gunicorn.pid) # 平滑升级

相关链接