本文 AI 產出,尚未審核

FastAPI 部署與架構(Deployment & Architecture)

主題:部署架構(Uvicorn, Gunicorn, Nginx)


簡介

在開發完成 FastAPI 應用之後,最關鍵的步驟往往是 如何把程式碼安全、穩定且高效地提供給使用者。單純在開發機上執行 uvicorn app:app --reload 雖然方便,但在正式環境中會面臨效能、可靠性與安全性的挑戰。

本篇文章將說明在 Linux 伺服器 上常見的三層部署架構——Uvicorn(ASGI 伺服器)、Gunicorn(多工管理器)與 Nginx(反向代理、靜態檔案服務與 TLS 終端),並提供完整的設定範例與最佳實踐,讓你能快速將 FastAPI 應用上線,且具備可擴充與容錯的基礎。


核心概念

1. 為什麼需要三層架構?

層級 角色 主要任務
Uvicorn ASGI 伺服器 直接執行 FastAPI 程式碼,處理 HTTP 請求與回應的非同步 I/O。
Gunicorn WSGI/ASGI 進程管理器 產生多個 worker(Uvicorn)以利用多核心 CPU,並在 worker 異常時自動重啟。
Nginx 反向代理 & 靜態檔案伺服器 代理外部請求到 Gunicorn,提供 TLS/SSL、負載平衡、緩存、限流與 404/500 錯誤頁面。

將三者結合 能兼顧 效能(多核心利用)、穩定性(worker 監控)與 安全性(HTTPS、IP 限制)。


2. Uvicorn:輕量級 ASGI 伺服器

Uvicorn 是官方推薦的 FastAPI 執行環境,支援 HTTP/1.1、WebSocket 以及 HTTP/2(需 uvicorn[standard])。在開發階段常用 --reload 參數自動重新載入程式碼,但在正式環境應關閉此功能,以避免不必要的資源消耗。

範例 1:最簡單的 Uvicorn 啟動指令

# 安裝 uvicorn(含標準套件)
pip install "uvicorn[standard]"

# 直接執行(僅單一 worker,適合測試或小流量)
uvicorn main:app --host 0.0.0.0 --port 8000

註解main:app 表示在 main.py 中的 app 變數(FastAPI 實例)。

範例 2:使用 --workers 啟動多個 worker(不建議在正式環境直接使用)

uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000

說明:Uvicorn 本身支援多 worker,但不會自動監控或自動重啟失敗的 worker;這正是引入 Gunicorn 的原因。


3. Gunicorn + Uvicorn Workers

Gunicorn 是成熟的 WSGI/ASGI 進程管理器,提供 預先 fork自動重啟Graceful shutdown 等功能。搭配 uvicorn.workers.UvicornWorker,Gunicorn 會在每個 worker 中啟動 Uvicorn,達成多核心佈局。

範例 3:使用 Gunicorn 啟動 FastAPI(最常見的部署指令)

# 安裝必要套件
pip install gunicorn uvicorn[standard]

# 啟動 4 個 worker,每個 worker 使用 async 事件迴圈 (uvloop)
gunicorn main:app \
    -w 4 \
    -k uvicorn.workers.UvicornWorker \
    --bind 0.0.0.0:8000 \
    --log-level info \
    --access-logfile -

重點

  • -w 4:根據伺服器 CPU 核心數調整。
  • -k uvicorn.workers.UvicornWorker:指定使用 Uvicorn 作為 worker。
  • --log-level info--access-logfile -:將日誌直接輸出到 stdout,方便 Docker / systemd 收集。

範例 4:在 systemd 服務單元中使用 Gunicorn(Linux 服務化)

# /etc/systemd/system/fastapi.service
[Unit]
Description=FastAPI application with Gunicorn
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/fastapi
Environment="PATH=/var/www/fastapi/venv/bin"
ExecStart=/var/www/fastapi/venv/bin/gunicorn main:app \
    -w 4 \
    -k uvicorn.workers.UvicornWorker \
    --bind unix:/run/fastapi.sock \
    --log-level info \
    --access-logfile -

# 確保服務在失敗時自動重啟
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

說明:此範例將 Gunicorn 綁定到 Unix domain socket(/run/fastapi.sock),稍後 Nginx 會透過此 socket 代理請求。


4. Nginx:前端代理與安全層

Nginx 在部署架構中扮演 入口門戶 的角色,負責 TLS 終端、負載平衡、靜態檔案服務、以及將請求轉發給後端的 Gunicorn。使用 Nginx 可以讓 FastAPI 專注於業務邏輯,而不必處理 SSL、請求緩衝或大量並發連線的底層細節。

範例 5:基本的 Nginx 反向代理設定(使用 Unix socket)

# /etc/nginx/sites-available/fastapi.conf
server {
    listen 80;
    server_name api.example.com;

    # 1️⃣ 轉發所有 HTTP 請求到 Gunicorn
    location / {
        proxy_pass http://unix:/run/fastapi.sock;
        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;
    }

    # 2️⃣ 服務靜態檔案(如前端 SPA 的 build 目錄)
    location /static/ {
        alias /var/www/fastapi/static/;
        expires 30d;
        access_log off;
    }

    # 3️⃣ 錯誤頁面自訂
    error_page 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

重點

  • proxy_pass http://unix:/run/fastapi.sock; 直接使用 Unix socket,效能比 TCP 更佳。
  • proxy_set_header 確保 FastAPI 能正確取得原始 client IP 與協定(HTTP/HTTPS)。

範例 6:啟用 TLS(Let's Encrypt)與 HTTP → HTTPS 重新導向

# /etc/nginx/sites-available/fastapi-ssl.conf
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 同上面的 proxy 設定
    location / {
        proxy_pass http://unix:/run/fastapi.sock;
        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 /var/www/fastapi/static/;
        expires 30d;
        access_log off;
    }
}

說明:使用 Let's Encrypt 的自動續期腳本(certbot renew --nginx)即可維持證書有效。


常見陷阱與最佳實踐

陷阱 可能的後果 解決方案或最佳實踐
直接用 uvicorn --reload 上線 記憶體洩漏、效能不佳、無自動重啟 只在開發環境使用 --reload,正式環境改用 Gunicorn + UvicornWorker
未設定 proxy_set_header X-Forwarded-Proto FastAPI 產生的 URL 仍是 http,導致 OAuth、CSRF 等失效 在 Nginx 代理區塊加入 proxy_set_header X-Forwarded-Proto $scheme;
使用 TCP 端口(127.0.0.1:8000)而非 Unix socket 多一層 TCP 握手,稍微降低效能,且防火牆規則較複雜 若同機器內部通訊,優先使用 unix:/run/fastapi.sock
Worker 數設定過少 單核 CPU 無法發揮全部效能,請求排隊 一般建議 workers = 2 * CPU + 1,視應用 I/O 密集度調整。
未對 Nginx 設定 client_max_body_size 大檔案上傳被 413 斷開 若需要上傳檔案,加入 client_max_body_size 100M;(依需求調整)。
未使用 systemd 或容器化管理 手動啟動、無法自動重啟、部署不一致 建議將 Gunicorn 包裝成 systemd 服務,或使用 Docker + docker‑compose

最佳實踐小結

  1. 分離關注點:Nginx 處理網路安全、TLS、靜態檔;Gunicorn 管理多 worker;Uvicorn 處理非同步請求。
  2. 使用環境變數或 .env 管理設定(如 HOST, PORT, LOG_LEVEL),避免硬編碼。
  3. 日誌集中:將 stdoutstderr 交給 systemd 或容器日誌系統(如 journaldDocker logs),方便監控與排錯。
  4. 健康檢查:在 Nginx 或 Kubernetes 中配置 /health 端點,讓負載均衡器能自動剔除不可用的實例。

實際應用場景

場景 需求 推薦架構
小型內部工具(員工使用、流量少) 快速部署、維護成本低 直接使用 uvicorn + systemd,不必加 Nginx。
對外 API 服務(數千 QPS、需要 TLS) 高併發、HTTPS、錯誤頁面自訂 Nginx → Gunicorn(UvicornWorker),Worker 數依 CPU 調整,使用 Let's Encrypt。
容器化微服務(K8s) 動態伸縮、藍綠部署、服務網格 Dockerfile 包含 uvicorn,K8s Deployment 使用 replicas,Ingress(NGINX‑Ingress)作為外部入口,TLS 交由 Ingress 處理。
需要長時間 WebSocket 連線(即時聊天、推播) WebSocket 支援、低延遲 確保 Nginx proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;,使用 Uvicorn--ws websockets(默認已支援)。
大型資料下載(檔案服務) 大檔案傳輸、斷點續傳 靜態檔案交給 Nginx alias,設定 sendfile on;tcp_nopush on;,避免 FastAPI 介入大量 I/O。

總結

部署 FastAPI 時,Uvicorn、Gunicorn、Nginx 三者的配合是業界最成熟且可靠的方案。透過:

  • Uvicorn 提供非同步的 ASGI 執行環境,
  • Gunicorn 以多 worker 方式充分利用 CPU,並自動監控與重啟失敗的工作進程,
  • Nginx 作為前端代理,負責 TLS、負載平衡、靜態檔案與安全防護,

我們可以在 效能穩定性安全性 之間取得最佳平衡。只要遵守本文列出的 常見陷阱最佳實踐(如適當設定 worker 數、使用 Unix socket、將日誌交給 systemd),即可在任何規模的專案中快速、穩定地上線 FastAPI 服務。


小提示:在正式上線前,務必使用 負載測試工具(如 heylocust)驗證 Nginx → Gunicorn → Uvicorn 整體的吞吐量與延遲,並持續監控 CPU%Memory%response time,讓你的 FastAPI 服務在實際營運中保持最佳表現。