簡體   English   中英

Google App Engine 上的同步和異步 Python FastAPI 腳本

[英]Sync & Async Python FastAPI scripts on Google App Engine

我嘗試在本地運行以下 py 文件script.py

from fastapi import FastAPI
import asyncio
import time

app = FastAPI()

@app.get('/async/')
async def func(text: str):
    await asyncio.sleep(5)
    return {'text': text}


@app.get('/sync/')
async def func(text: str):
    time.sleep(5)
    return {'text': text}

使用uvicorn script:app --reload

向同步端點http://127.0.0.1:8000/sync/?text=test發出 10 個並發請求時,每個調用需要 5 秒並阻塞下一個,總時間為 50 秒

當向異步端點http://127.0.0.1:8000/async/?text=test發出 10 個並發請求時,每個調用需要 5 秒,總時間也是 5 秒,因為它是非阻塞的。


我嘗試使用entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker script:app並進行了相同的測試而不是本地測試,並得到以下結果:

當向同步端點發出 10 個並發請求時,總時間為 12 秒,所有 10 個請求都在同一個實例上執行。 (1000 個並發請求在 20 多個實例上花費了 60 秒)

並且向異步端點發出 10 個並發請求時,總時間為 5 秒,所有 10 個請求都在同一個實例上執行。 (1000 個並發請求在 20 多個實例上花費了 30 秒)


為什么在 GAE 上,10 個並發請求的同步代碼需要 12 秒而不是 50 秒?

我怎樣才能在 GAE 上同時為同步端點運行所有 10 個請求,以在 5 秒內將它們全部獲取?

在您的 gunicorn 命令中,您指定了選項-w 4 ,這意味着生成了 4 個工作進程( https://docs.gunicorn.org/en/stable/settings.html#worker-processes )。

即使在阻塞同步代碼的情況下,它也是一種啟用並發的常用方法。 您的 10 個請求被分配給工作人員(10 個請求 * 5 秒 / 4 個工作人員 = 12.5 秒)。

如果你像這樣運行它:

gunicorn -w 1 -k uvicorn.workers.UvicornWorker script:app

你會經歷 50 秒的等待。

但仍然強烈建議產生幾個工人。


現在對於同步部分,這里有一個關於 FastAPI 的有趣技術細節。 如果您將路由或依賴項定義為async ,它將在主進程中運行,無論您是否在內部運行阻塞代碼。

這就是您的/sync端點阻塞的原因。

但是,如果將其定義為標准非異步 function,FastAPI 將在線程池中運行它以避免阻塞主進程。

文檔: https://fastapi.tiangolo.com/async/?h=technical#path-operation-functions

如果您像這樣編寫/sync端點:

@app.get('/sync/')
def func(text: str):  # Just removed the async keyword
    time.sleep(5)
    return {'text': text}

您會注意到端點不再阻塞主進程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM