Python FastAPI 异步变量共享



如果我有下面的代码,变量service如何影响端点的异步性质?变量会被共享吗?还是在使用时会将其锁定,从而阻止其他端点访问它,直到当前端点完成?

我问上面的假设服务实例是无状态的,即如果我在每个端点中创建一个服务实例,这将是等效的。我不愿意这样做,因为我不知道哪个更耗时,实例化和销毁服务对象或共享一个?

from typing import List, Union
from fastapi import APIRouter, Body, Depends
# Service definition
router = APIRouter()
service = Service()
@router.post("/a", response_model=Union[A, None])
async def x():
service.start()
pass
@router.post("/b", response_model=Union[B, None])
async def y():
service.stop()
pass

变量服务将如何影响端点的异步性质?

首先,如果您的service.stop()不是协程,则异步不会执行任何上下文切换。

这意味着它将阻止

这也意味着你的函数必须是awaitable的,它必须是屈服的。

还是在使用时会被锁定

如果可能存在争用条件,它不会自动锁定。您需要锁定它(请参阅异步。锁())。

但是,如果您的代码不执行任何上下文切换。您不必担心这一点,因为两个协程不能同时执行,并发性不是并行性

在事件循环(执行协程的地方)中,协程生成要恢复的事件。事件循环能够等待这些事件发生。但是在等待的同时,它也可以等待其他事件,或者它可以处理其他事件。这仅在您有一个协程时才有效,事件通信由事件循环的生成控制完成。

但是当两个事件共享同一个List时你应该怎么做,你需要锁定它。


为了更清楚地说明这一点,假设您的代码是一家餐厅,协程是女服务员,您向女服务员下达命令,然后她前往厨师(事件循环)

你需要等待,你也不能分享酋长,而酋长可以同时做两个汉堡包(处理两个不同的事件)

当他没有足够大的网格来同时制作两个汉堡包(共享对象)时会发生什么?

当您的订单正在等待时,您需要锁定网格两个使其他客户订购,但您不能共享网格,因为您有一个网格,您需要说"嘿,我需要锁定这里">

但是你仍然可以吃沙拉(其他协程不会被阻止)。


所以在这种情况下,如果我在它们中的每一个中执行 Service().start() 会不会更慢?

TL;博士

这个问题完全取决于您的start()函数的作用以及它的作用。

好的,但我需要更好地理解异步。

然后假设您有以下代码

async def x():
a = await service.start()
return a
  1. 这将为生成变量分配堆栈空间service().start()
  2. 事件循环将执行此操作并跳转到下一条语句
    1. 一旦start()get被执行,它将推动调用堆栈的值
    2. 这将存储堆栈和指令指针。
    3. 然后它将生成的变量从service().start()存储到a,然后它将恢复堆栈和指令指针。
  3. 当涉及到return a时,这会将 a 的值推送到调用堆栈。
  4. 毕竟它将清除堆栈和指令指针。

请注意,我们能够完成所有这些操作,因为service().start()是一个协程,它是yielding而不是返回。

乍一看,您可能不清楚,但正如我提到的asyncawait只是用于声明和管理协程的花哨语法。

import asyncio
@asyncio.coroutine
def decorated(x):
yield from x 
async def native(x):
await x 

但是这两个功能是相同的,做完全相同的事情。您可以考虑yield from一个或多个函数链接在一起。

但是,要深入了解异步 I/O,我们需要了解它的作用以及它如何在下面执行。

在大多数操作系统中,基本 API 可用于select()poll()系统调用。

这些接口使 API 的用户能够检查是否有任何应处理的传入 I/O。

例如,您的 HTTP 服务器想要检查是否有任何网络数据包到达以便为它们提供服务。借助此系统调用,您可以检查这一点。

当我们检查select()手册页时,我们将看到此描述。

select() 和 pselect() 允许程序监视多个文件解 脚本,等待一个或多个文件描述符变为 "准备好"用于某些类别的 I/O 操作(例如,可能的输入)。 一个文件如果可以执行相应的描述符,则认为描述符已准备就绪‐ 冲击 I/O 操作

这为您提供了一个非常基本的概念,并解释了异步 I/O 的本质。

它允许您检查是否可以读取和写入描述符。

它通过不阻塞其他内容使您的代码更具可扩展性。作为奖励,您的代码会变得更快,但这不是异步 I/O 的实际目的

所以要整理。

事件循环只是不断产生,而某些东西已经准备好了。通过这样做,它不会阻塞。

最新更新