本內容是對知名性能評測博主 Anton Putra Python (FastAPI) vs Go (Golang) (Round 2) Performance Benchmark 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準
介紹
這是第二輪關于 FastAPI 和 Golang 的對比測試。我幾天前運行了前一次的基準測試,到目前為止,我已經收到了 13 個關于 Python 性能改進的 Pull Request。如果你是一名開發者,我建議你先觀看之前的基準測試,并對比視頻描述中提供的源碼和所有的 Pull Request,這樣可以幫助你避免我在上一次基準測試中犯的錯誤。
在第一輪測試中,我們將測量以下指標:
- 使用 90% 分位數 測量客戶端每個請求的延遲。
- 使用每秒請求數(Requests Per Second)來衡量吞吐量。
- 應用程序的 CPU 使用率。
- 內存使用情況。
- 可用性或錯誤率。
- CPU 限制(CPU Throttling)情況。
這些測試將在 AWS 的生產級 Kubernetes 集群中運行。
在第二輪測試中,我們將模擬一個真實的用例:應用程序接收請求后,將數據保存到關系型數據庫中,并使用緩存來提高性能。數據庫使用 Postgres 17.2,緩存使用 Memcached。如果你感興趣,可以觀看我之前對比 Redis 和 Memcached 的視頻結果(結果差距很大)。
所有的基準測試都在 AWS 上運行,使用了不同類型的 EC2 實例。目前,我主要使用基于 ARM 架構的 Graviton 實例,因為它們價格更低。
-
Postgres 使用存儲優化型的 i8g.large 實例。
-
緩存使用 m8g.large 實例。
-
Kubernetes 集群中的監控組件(如 Prometheus 和 Grafana)及負載生成客戶端,運行在計算優化型實例上。
-
每個應用程序運行在專用虛擬機上,使用了 m7a.large 實例,并通過 Tolerations 和 Affinity 設置實現隔離(以能夠使它們運行在自己專用的虛擬機上面)。
AWS 的費用不低,為了支持我的頻道和支付這些基礎設施成本,我提供一對一咨詢和其他服務。詳情請查看視頻描述。
第一輪測試(靜態內容)
好了,讓我們開始第一輪測試。這是第二輪測試了,我建議你先觀看使用未經優化的 Python 代碼進行的第一次基準測試,然后與這次測試進行對比。在第一輪測試中,我們讓應用返回硬編碼的對象。
這次測試中:
- 我使用了 FastAPI 推薦的默認 Web 服務器 Uvicorn,并配置了兩個工作線程(workers)。
- 端點使用了異步處理(Async Handler)。
雖然在第一次基準測試中性能稍好,但最終還是失敗了并恢復運行。
在這次測試中,性能稍微更穩定,但只能達到 每秒 11,000 請求。雖然差距不是很大,但對性能還是有影響。在運行到每秒約 11,000 請求時,由于 CPU 限制,開始出現失敗,延遲大幅上升,可用性下降。
我原本期望經過這些優化和收到的眾多 Pull Request(你可以在視頻描述中找到所有這些 Pull Request),性能會更好。不過,我會繼續運行測試,直到 Go 應用程序也開始出現失敗。
Golang 的表現依舊出色,可以達到 每秒 60,000 到 65,000 請求,這是非常不錯的性能。雖然不是最頂尖的,但一些語言(比如 Rust 和 Zig)在類似測試中可以達到 每秒 100,000 請求。但無論如何,在這次測試中,Go 的效率遠遠高于 FastAPI。
接下來,我們打開每個測試指標的圖表:
- 每秒請求數(Requests Per Second)
- Python 達到了 每秒 11,000 請求,而 Go 達到了 每秒 66,000 請求。
-
延遲(Latency)
- 對于面向客戶端的應用程序來說,延遲是最重要的指標之一,而 Go 在這一點上表現得更好。
- CPU 使用率
- FastAPI 很快耗盡了所有可用 CPU。
- 可用性(Availability)
- 內存使用(Memory Usage)
- CPU 限制(CPU Throttling)
在這次測試中,FastAPI 的表現并不好。但我會繼續測試其他 Python 框架,例如 Starlette(FastAPI 的底層框架),或者直接創建一個 ASGI Python 應用,看看能否接近 Go 應用的性能。
第二輪測試(Postgres + Memcached)
第二輪測試主要針對真實場景的改進,結果確實在真實用例中有顯著提升。在這個測試中,應用程序需要:
- 解析請求體。
- 將記錄插入到關系型數據庫中。
- 將數據緩存到 Redis 或 Memcached 中。
如果你想改進你的 Python 應用程序,我建議對比兩種實現,并查看儀表板上的性能差異。
在之前的基準測試中,FastAPI 只能達到 每秒 750 請求。在這次改進后,性能提升到了 每秒 2,500 請求。相比之前的測試,這是一個巨大的改進,但仍遠不及 Go 應用。
在這次測試中,我們還測量了以下指標的延遲:
- 數據庫插入操作的延遲。
- 保存數據到緩存的函數調用延遲。
- 總體 POST 請求的延遲。
雖然 Python 表現比之前好了許多,但在性能上仍然遠不及 Go 應用。這次測試中,我收到了很多 Pull Request,但這已經是目前的最佳性能了。我覺得需要嘗試其他 Python 框架,尋找能夠接近 Go 應用性能的解決方案。
未來,我將只測試 Python 框架,比如 Django、Flask 和 FastAPI。
接下來打開每個測試指標的圖表:
- 每秒請求數(Requests Per Second)
- FastAPI 最高達到了 每秒 2,600 請求,而 Go 達到了 每秒 20,000 請求。
- 在之前的測試中,Go 的性能受限于 Memcached 的連接數設置。這次測試中,我增加了閑置連接數限制,所以 Go 能夠充分利用 CPU,達到更高的請求數。
- 總體 POST 請求延遲(Overall Latency for POST Requests)
- 數據庫操作延遲(Database Operation Latency)
- 緩存延遲(Cache Latency)
- CPU 使用率(CPU Usage)
- Postgres 和 Memcached 的 CPU 使用率
- 從圖中可以看到,對于相同數量的數據庫和緩存請求,緩存只需要很少的資源。因此,使用緩存不僅可以顯著提高應用性能,還可以通過減少資源使用來降低基礎設施成本。
- Postgres 連接池(Connection Pool)
- 每個應用程序創建并維護了一個最大連接數為 500 的 Postgres 連接池。
- 內存使用(Memory Usage)
總結
我將繼續尋找并測試更快的 Python 框架。如果你感興趣,可以查看我其他的基準測試視頻。感謝觀看,我們下次見!