python-3.x Tortoise-orm with FastApi从数据库中获取数据是阻塞/同步而不是异步/非阻塞

w7t8yxp5  于 2023-04-08  发布在  Python
关注(0)|答案(1)|浏览(246)

使用fastapi和tortoise-orm==0.19.3。表Server有大约25,000条记录。
我用端点/servers/获取所有这些。

@server_router.get("/servers")
async def get_servers():
    ret = await ServerPydantic.from_queryset(Server.all())
    return ret

没有分页和偏移量,我这样做是为了测试。
还有另一个终点:

@server_router.get("/servers-test/{s}")
async def test(s:int):
    print(f"sleeping for {s} seconds")
    await asyncio.sleep(s)
    return {"test": "test"}

我向端点/server发出请求,然后快速向端点/servers-test/{s}发出两个请求:

  • curl http://127.0.0.1/servers,这需要一些时间,大约4- 5秒
  • curl http://127.0.0.1/servers-test/5,就在第一个请求之后
  • curl http://127.0.0.1/servers-test/0紧接在上一个请求之后

通过查看函数中的print语句,我可以立即判断出最后一个请求根本没有被处理,它被调用/servers阻塞,直到第一个请求完成。只有这样,其他两个请求才开始运行。
如果我做了

@server_router.get("/servers")
async def get_servers():
    asyncio.sleep(30)
    print("sleeping done")
    ret = await ServerPydantic.from_queryset(Server.all())
    return ret

基本上我只是添加了asyncio.sleep(30)。然后我重复上面提到的步骤。

  • curl http://127.0.0.1/servers,这将需要很长时间,因为asyncio.sleep(30)
  • curl http://127.0.0.1/servers-test/5,在第一个请求之后,它立即得到服务
  • curl http://127.0.0.1/servers-test/0在上一个请求之后,它立即得到服务

如果我在30秒后发出请求,那么请求会再次被阻止。所以很明显,Server.all()会阻止I/O。这是意料之外的。我做错了什么吗?我在Google和Tortoise-orm Github上搜索了问题,但没有找到相关信息。
更新:我试过使用sqlalchemy,同样的事情发生了。所以它不是Tortoise-orm相关的I geuess。
我试过这个:

# some sessions and schemas setup are not shown here.
@app.get("/serversv2", response_model=ServerList)
async def get_all_servers(session: AsyncSession = Depends(get_session)):
    result = await session.execute(select(Server1))
    servers = result.scalars().all()
    return {"servers": servers}

它仍然阻止其他请求。

waxmsbnn

waxmsbnn1#

您没有显示Server对象是什么-但如果这是一个同步调用,它将阻塞它们。
如果你将结果传递给Pydantic中的异步调用,这并不重要:对X1 M1 N1 X的调用将仅在 * X1 M2 N1 X已经返回之后 * 发生。
由于您没有发布所有代码,因此我不能在答案中如此肯定-但也许Server对象本身是可迭代的,如果您不对它调用all(),那么“做正确的事情”?然后您只需将Server对象本身传递给from_queryset调用(这听起来像是应该做的事情,无论如何-.all()方法的返回是查询结果本身,而不是查询集)。

相关问题