昨天我們了解了 WSGI 和 ASGI 這兩個重要的溝通規範。今天,我們來認識一下將這些規範付諸實踐的關鍵角色:Application Server,特別是與 FastAPI 合作無間的 Uvicorn 和 Gunicorn。
在我們 Day 09 提到的架構中,Application Server(也常被稱為 WSGI/ASGI Server)扮演著至關重要的翻譯官角色。它位於 Web Server (如 Nginx) 和我們的 FastAPI 應用程式之間,主要職責是:
沒有 Application Server,Nginx 不知道如何與一個 Python 物件溝通,反之亦然。
Uvicorn 是一個閃電般快速的 ASGI 伺服器,它的名字就代表了它的核心:uvloop
和 httptools
。uvloop
是 asyncio
事件循環的超快速替代品,這使得 Uvicorn 在處理非同步任務時性能極佳。
它在架構中的角色:Uvicorn 是專為 ASGI 打造的 Application Server。當你執行 FastAPI 應用程式時,Uvicorn 會載入你的程式碼,監聽網路埠號,並將收到的請求轉換成 ASGI 事件,交給 FastAPI 處理。
FastAPI 的核心是非同步的,它依賴 ASGI 規範來實現高效的並行處理。因此,FastAPI 必須由一個 ASGI 伺服器來運行。Uvicorn 是 FastAPI 官方推薦的伺服器,因為它性能卓越,且與 FastAPI 和 Starlette 完美契合。
啟動一個 FastAPI 應用程式非常簡單:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
在終端機中執行:
uvicorn main:app --reload
main
是指 main.py
檔案,app
是指在 main.py
中建立的 FastAPI
實例。--reload
參數會在程式碼變更時自動重啟伺服器,非常適合開發階段。
Gunicorn (Green Unicorn) 是一個非常成熟、穩定且被廣泛使用的 WSGI 伺服器。它以其簡單的設定和強大的程序管理能力而聞名。Gunicorn 透過預先 fork 多個 Worker Process 來實現並行處理,每個 Worker 都是一個獨立的 Unix 程序,可以獨立處理請求。
它在架構中的角色:Gunicorn 是一個純粹的 WSGI 伺服器。它無法直接運行 ASGI 應用程式,如 FastAPI。
那麼,如果 Gunicorn 這麼穩定,而 Uvicorn 性能又這麼好,我們能否將兩者結合呢?答案是肯定的!這也 曾經
是生產環境中部署 FastAPI 的推薦方式。
我們可以讓 Gunicorn 作為程序管理器 (Process Manager),並使用 Uvicorn 作為其 Worker 類別。
架構分工:
這樣配置,我們既獲得了 Gunicorn 的穩定性和 multi-process 管理能力,又能享受到 Uvicorn 處理非同步請求的極致性能。
啟動指令如下:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
-w 4
:啟動 4 個 worker process。-k uvicorn.workers.UvicornWorker
:指定 Gunicorn 使用 Uvicorn 的 worker 類別來運行。這就是讓 Gunicorn 能夠管理 ASGI 應用的關鍵。前面有提到,Gunicorn + Uvicorn 的組合已經不再是推薦做法,FastAPI 在文件中也表示 tiangolo/uvicorn-gunicorn-fastapi 這個「前」官方 Docker image 已經 deprecated 了 (2024 年 8 月)。
主要有 2 個原因:
Uvicorn 專案本身不斷發展,其內建的 Worker 管理功能也日趨完善。現在,您可以直接透過 uvicorn
指令加上 --workers
參數來啟動多個 Worker 進程:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
這個指令會啟動一個主進程和四個 Worker 進程。Uvicorn 的主進程同樣具備了監控和重啟異常終止的 Worker 的能力。雖然其功能豐富度可能仍不及 Gunicorn,但對於大多數常見的生產環境需求而言,已經綽綽有餘,且省去了一個額外的依賴。
現代應用程式的部署越來越依賴 Docker、Kubernetes (K8s) 等容器化技術。在這樣的架構下,進程管理和服務健康的責任,逐漸從應用程式層級轉移到了基礎設施層級。在這種模式下,Gunicorn 的角色被 K8s 等更高層級的工具所取代。在容器內僅運行 Uvicorn(帶或不帶 --workers
),可以讓容器的啟動和管理更為單純。
就直接使用 uvicorn
搭配 --workers
,例如:
uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
或是直接用 FastAPI CLI:
fastapi run --workers 4 main.py
其他部屬的細節,就等最後講到容器化與部屬時,再進行討論~
FastAPI 的非同步特性決定了它需要一個 ASGI 伺服器來運行。Uvicorn 作為高性能的 ASGI 伺服器,是 FastAPI 的完美搭檔。無論是開發階段還是生產環境,現在都推薦直接使用 Uvicorn(搭配 --workers
參數)或 FastAPI CLI 來運行應用程式。隨著容器化技術的普及和 Uvicorn 自身功能的完善,這種簡潔的部署方式已經能夠滿足大多數生產環境的需求。