FastAPI + uvicorn:是否有可能接受多个连接与单个工作者?



下面是一些示例代码来演示这个问题:

import asyncio
import datetime
import time
import uvicorn
from fastapi import FastAPI
from starlette.responses import PlainTextResponse
app = FastAPI()

@app.get(path="/sync")
def get_sync():
print(f"sync: {datetime.datetime.now()}: Before sleep")
time.sleep(5)
print(f"sync: {datetime.datetime.now()}: After sleep")
return PlainTextResponse(content=f"sync: {datetime.datetime.now()}: Hello, World!")

@app.get(path="/async")
async def get_async():
print(f"async: {datetime.datetime.now()}: Before sleep")
await asyncio.sleep(5)
print(f"async: {datetime.datetime.now()}: After sleep")
return PlainTextResponse(content=f"async: {datetime.datetime.now()}: Hello, World!")

if __name__ == "__main__":
uvicorn.run(app=app, host="0.0.0.0", port=1911)
  1. 选择以上任意端点:GET /syncGET /async
  2. 从两个不同的web浏览器选项卡调用端点(或使用cURL等)来创建两个并行请求
  3. 第一个请求阻塞第二个请求

我期望GET /sync在线程池上运行。我期望GET /async使用一些asyncio魔法。

我不能使用多个工作者。是否有一个解决方案,允许与单个工作线程并发请求?

供参考:我使用Python 3.7(64位/Win10)和最新版本的FastAPI + unvicorn。

从浏览器调用web端点将被阻塞(在客户端),因为它正在等待响应。为了正确地测试它,您需要异步调用它。例如,您可以使用单独的python脚本

import asyncio
import aiohttp
from aiohttp import ClientSession
async def call_async(session: ClientSession, url: str):
async with session.get(url) as result:
async def main():
async with aiohttp.ClientSession() as session:
url = 'https://localhost:5000/async'  # change port 
tasks = [call_async(session, url) for i in range(5)]
for finished_task in asyncio.as_completed(tasks):
print(await finished_task)
asyncio.run(main())

最新更新