FastAPI 異步處理最佳實踐指南
FastAPI 的異步處理機制
FastAPI 框架無論是否明確指定 async
,都會以異步方式運行。框架會根據函數的宣告方式進行不同的處理:
執行方式差異
def
宣告的函數:會被丟到獨立的 thread pool 中執行async def
宣告的函數:會在 event loop 中執行- 一般同步函數:會被放到 thread pool 中執行(取決於 worker 和 thread 數量)
關鍵原則:避免阻塞 Event Loop
⚠️ 重要警告
不要在 async def
函數中使用同步(非 await)的 I/O 操作,這會讓處理變成序列化執行,嚴重降低性能。
為什麼會發生阻塞?
當你使用 await
時,Python 會暫停當前協程的執行,直到被等待的協程完成。在協程被暫停期間,Python 的 event loop 可以處理其他協程。
但如果在 async def
函數中進行同步 I/O 操作而不使用 await
:
- Event loop 無法暫停(suspend)該任務
- 其他請求必須等待當前操作完成
- 造成看似序列化的執行模式
- 大量請求堆積可能導致記憶體使用增加
官方文檔說明
When you declare a path operation function with normal
def
instead ofasync def
, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
何時使用 Async/Await
適合使用的場景
- 資料庫 I/O 操作
- 網路請求和 Socket 通訊
- 文件讀寫操作
- 其他 I/O 密集型任務
不適合使用的場景
- CPU 密集型任務(考慮使用 multiprocessing 或 threading)
- 調用不支援
await
的第三方函數庫 - 簡單的計算或資料處理
最佳實踐範例
❌ 錯誤做法
@app.get("/bad")
async def bad_endpoint():
# 這會阻塞 event loop
result = some_sync_db_call() # 沒有 await
return result
@app.get("/also-bad")
async def also_bad_endpoint():
# 在 async 函數中使用同步的第三方庫
data = requests.get("https://api.example.com") # 阻塞操作
return data.json()
✅ 正確做法
@app.get("/good-async")
async def good_async_endpoint():
# 使用支援 async 的資料庫操作
result = await some_async_db_call()
return result
@app.get("/good-sync")
def good_sync_endpoint():
# 使用 def 讓 FastAPI 在 thread pool 中執行
result = some_sync_db_call()
return result
@app.get("/good-mixed")
def good_mixed_endpoint():
# 第三方同步庫在 thread pool 中執行
data = requests.get("https://api.example.com")
return data.json()
依賴注入的考量
在 FastAPI 的 Depends
中也要遵循相同原則:
# ❌ 錯誤
async def bad_dependency():
return some_sync_operation() # 阻塞
# ✅ 正確
async def good_async_dependency():
return await some_async_operation()
# ✅ 也正確
def good_sync_dependency():
return some_sync_operation() # 在 thread pool 中執行
總結
- 理解執行機制:
def
使用 thread pool,async def
使用 event loop - 避免混用:不要在
async def
中進行同步 I/O 操作 - 選擇適當方式:
- 有真正的異步 I/O 需求時使用
async def
- 使用同步函數庫時使用
def
- 有真正的異步 I/O 需求時使用
- 保持一致性:在 path operations 和 dependencies 中保持一致的模式
所謂的「效能」比較好指的是「響應能力」與「交互性」好,至於 CPU time 不會有什麼差異,遵循這些原則可以確保你的 FastAPI 應用獲得最佳的併發性能,避免不必要的阻塞和資源浪費。
發佈時間
2025-7-4