部署与运维
问题
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?
答案:
| 服务器 | 类型 | 适用 |
|---|---|---|
| Gunicorn | WSGI | Django、Flask |
| Uvicorn | ASGI | FastAPI、Starlette |
| Gunicorn + Uvicorn Worker | ASGI | FastAPI 生产部署(推荐) |
| uWSGI | WSGI | Django(功能多但配置复杂) |
Q2: Worker 数量怎么定?
答案:
- CPU 密集:
workers = CPU核心数 + 1 - IO 密集:
workers = CPU核心数 * 2 + 1 - 异步框架:可以用更少 Worker(async 本身有并发能力)
Q3: 如何实现零停机部署?
答案:
- Gunicorn 信号:
kill -USR2 <pid>优雅重启 - Blue-Green 部署:两套环境切换
- Rolling Update:K8s 滚动更新
# Gunicorn 优雅重启
kill -HUP $(cat gunicorn.pid) # 重新加载配置
kill -USR2 $(cat gunicorn.pid) # 平滑升级