繁体   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