FastAPI Nginx与Gunicorn生产部署完全指南

📂 所属阶段:第五阶段 — 工程化与部署(实战篇)
🔗 相关章节:Docker容器化部署 · Pydantic Settings多环境配置

目录

生产部署架构概述

为什么需要Nginx + Gunicorn架构?

直接用Uvicorn单进程跑FastAPI,一旦某个请求阻塞,所有请求都得等。加上Nginx和Gunicorn后,不仅能多进程处理,还能搞SSL、负载均衡、静态文件服务,稳得一批。

核心组件作用

组件职责
Nginx反向代理、SSL终止、静态文件、负载均衡
Gunicorn多进程管理、WSGI服务器
Uvicorn异步处理、ASGI支持(嵌在Gunicorn里用)

典型生产架构

互联网用户 → DNS → CDN → Nginx → Gunicorn Workers → FastAPI → 数据库

                 监控系统 ← 日志收集

Nginx反向代理配置

核心配置

直接上干货,把常用的配好:

# /etc/nginx/sites-available/daoman-api
upstream daoman_api {
    server 127.0.0.1:8000 weight=3 max_fails=2 fail_timeout=30s;
    server 127.0.0.1:8001 weight=3 max_fails=2 fail_timeout=30s;
    keepalive 32;
}

# HTTP自动跳HTTPS
server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;

    # SSL证书(后面讲怎么搞)
    ssl_certificate /etc/ssl/certs/your-domain.crt;
    ssl_certificate_key /etc/ssl/private/your-domain.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    # 安全头部
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # 日志
    access_log /var/log/nginx/daoman-access.log main;
    error_log /var/log/nginx/daoman-error.log warn;

    # Gzip压缩
    gzip on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript;

    # 主代理
    location / {
        proxy_pass http://daoman_api;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # 静态文件
    location /static/ {
        alias /var/www/daoman/static/;
        expires 30d;
        access_log off;
    }

    # WebSocket
    location /ws/ {
        proxy_pass http://daoman_api;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}

配置生效

# 软链到启用目录
sudo ln -s /etc/nginx/sites-available/daoman-api /etc/nginx/sites-enabled/
# 测试配置
sudo nginx -t
# 重载
sudo systemctl reload nginx

Gunicorn高性能配置

配置文件

在项目根目录建个gunicorn.conf.py

import multiprocessing

# 核心配置
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1  # 推荐公式
worker_class = "uvicorn.workers.UvicornWorker"  # 用Uvicorn处理异步
worker_connections = 1000
max_requests = 1000  # 处理1000个请求后重启,防内存泄漏
max_requests_jitter = 100  # 随机抖动,别同时重启
timeout = 300
preload_app = True  # 预加载,提性能

# 日志
accesslog = "/var/log/gunicorn/access.log"
errorlog = "/var/log/gunicorn/error.log"
loglevel = "info"

启动脚本

写个start.sh方便启动:

#!/bin/bash
export ENV="production"
mkdir -p /var/log/gunicorn
exec gunicorn main:app --config gunicorn.conf.py

用Systemd管理

建个/etc/systemd/system/daoman-api.service

[Unit]
Description=Daoman FastAPI Service
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/daoman
Environment="PATH=/opt/daoman/venv/bin"
ExecStart=/opt/daoman/venv/bin/gunicorn main:app --config gunicorn.conf.py
Restart=always

[Install]
WantedBy=multi-user.target

启动并开机自启:

sudo systemctl daemon-reload
sudo systemctl enable --now daoman-api

SSL证书配置与HTTPS

用Let's Encrypt免费证书,一键搞定:

# 安装Certbot
sudo apt update && sudo apt install certbot python3-certbot-nginx -y
# 获取证书(Certbot会自动改Nginx配置)
sudo certbot --nginx -d your-domain.com --agree-tos --email your-email@example.com
# 测试续期
sudo certbot renew --dry-run
# 自动续期定时任务(Certbot可能已经自动加了,检查一下)
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -

负载均衡与高可用

Nginx负载均衡

如果有多台后端服务器,改upstream就行:

upstream daoman_backend {
    server backend1.daoman.com:8000 weight=3;
    server backend2.daoman.com:8000 weight=3;
    server backend3.daoman.com:8000 weight=2;
    ip_hash;  # 保持会话,同一IP连同一后端
    keepalive 32;
}

应用健康检查

在FastAPI里加个健康检查端点:

from fastapi import FastAPI
from datetime import datetime

app = FastAPI()

@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "timestamp": datetime.now().isoformat()
    }

安全加固措施

Nginx安全配置

在之前的server块里再加几句:

# 隐藏Nginx版本号
server_tokens off;
# 限制请求大小(比如传文件别太大)
client_max_body_size 10M;
# 禁止访问敏感文件
location ~ /\. { deny all; access_log off; }
location ~* \.(bak|log|env)$ { deny all; access_log off; }

应用层安全

用FastAPI自带的TrustedHost中间件,防Host头攻击:

from fastapi.middleware.trustedhost import TrustedHostMiddleware

app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["your-domain.com", "*.your-domain.com"]
)

性能优化策略

Gunicorn优化

已经在配置文件里提过了,关键是workers数和preload_app

Nginx缓存

静态文件加了expires,动态接口如果可以缓存,也可以搞:

location /api/cached/ {
    proxy_pass http://daoman_api;
    proxy_cache my_cache;
    proxy_cache_valid 200 5m;  # 200响应缓存5分钟
}

应用缓存

aiocache给接口加缓存:

from aiocache import cached, Cache
from aiocache.serializers import JsonSerializer

cache = Cache(Cache.MEMORY, serializer=JsonSerializer(), ttl=300)

@app.get("/api/data")
@cached(cache=cache)
async def get_data():
    # 模拟慢查询
    import time
    time.sleep(0.5)
    return {"data": "cached data"}

监控与日志管理

日志配置

给FastAPI加个JSON日志,方便后续分析:

import logging
import json
from datetime import datetime

class JSONFormatter(logging.Formatter):
    def format(self, record):
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "message": record.getMessage()
        }
        return json.dumps(log_entry)

logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)

基础监控

psutil写个简单的监控脚本:

import psutil
import time

def monitor():
    while True:
        cpu = psutil.cpu_percent(interval=1)
        mem = psutil.virtual_memory().percent
        disk = psutil.disk_usage('/').percent
        print(f"CPU: {cpu}%, Mem: {mem}%, Disk: {disk}%")
        if cpu > 80 or mem > 85:
            print("⚠️  资源告警!")
        time.sleep(60)

if __name__ == "__main__":
    monitor()

故障排查与调试

常用排查命令

# 看服务状态
sudo systemctl status nginx daoman-api
# 看日志
sudo tail -f /var/log/nginx/daoman-error.log
sudo tail -f /var/log/gunicorn/error.log
# 看端口占用
sudo netstat -tlnp | grep :8000
# 测试API
curl https://your-domain.com/health

简单排查脚本

写个troubleshoot.sh一键查:

#!/bin/bash
echo "🔍 服务状态:"
sudo systemctl status nginx daoman-api --no-pager
echo -e "\n🔍 最近错误日志:"
sudo tail -n 20 /var/log/nginx/daoman-error.log
sudo tail -n 20 /var/log/gunicorn/error.log
echo -e "\n🔍 API测试:"
curl -s https://your-domain.com/health || echo "连接失败"

自动化部署脚本

写个deploy.sh,拉代码、更新依赖、重启服务一条龙:

#!/bin/bash
set -e
APP_DIR="/opt/daoman"
BACKUP_DIR="/opt/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

echo "🚀 开始部署..."

# 备份
sudo mkdir -p $BACKUP_DIR
sudo tar -czf $BACKUP_DIR/daoman_$TIMESTAMP.tar.gz $APP_DIR/ || true

# 拉代码
cd $APP_DIR
sudo git fetch origin && sudo git reset --hard origin/main

# 更新依赖
sudo $APP_DIR/venv/bin/pip install -r requirements.txt

# 重启服务
sudo systemctl restart daoman-api
sudo systemctl reload nginx

# 验证
sleep 5
if curl -s https://your-domain.com/health > /dev/null; then
    echo "✅ 部署成功!"
else
    echo "❌ 部署失败,尝试回滚..."
    sudo tar -xzf $BACKUP_DIR/daoman_$TIMESTAMP.tar.gz -C /
    sudo systemctl restart daoman-api
fi

总结

这套Nginx+Gunicorn+Uvicorn的部署方案,基本能满足中小项目的生产需求。关键点是:

  1. 合理配置Gunicorn workers数
  2. 搞个免费SSL证书
  3. 加安全头部和日志
  4. 写个自动化部署脚本
  5. 搞个简单的监控

🔗 相关教程