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。 |
最佳實踐小結
- 分離關注點:Nginx 處理網路安全、TLS、靜態檔;Gunicorn 管理多 worker;Uvicorn 處理非同步請求。
- 使用環境變數或
.env管理設定(如HOST,PORT,LOG_LEVEL),避免硬編碼。 - 日誌集中:將
stdout、stderr交給systemd或容器日誌系統(如journald、Docker logs),方便監控與排錯。 - 健康檢查:在 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 服務。
小提示:在正式上線前,務必使用 負載測試工具(如
hey、locust)驗證 Nginx → Gunicorn → Uvicorn 整體的吞吐量與延遲,並持續監控CPU%、Memory%、response time,讓你的 FastAPI 服務在實際營運中保持最佳表現。