异步FastAPI为什么授权中有同步代码?

问题描述 投票:0回答:1

大家好) 为什么授权有一个同步来创建和检查密码?

这是文档中的代码:

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user

@app.post("/token")
async def login_for_access_token(
    form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return Token(access_token=access_token, token_type="bearer")

调用此函数(authenticate_user)是同步的。在异步端点中。因此,事件循环将阻塞,循环将无法将控制权转移给另一个任务。

对此,我有几个疑问:

  1. 使用这个库是因为没有异步模拟吗?
  2. 循环阻塞会对应用程序的性能产生多大影响?
  3. 同时使用同步和异步代码的可接受程度如何?会有什么缺点?这可以做到还是应该避免?
python-3.x authorization python-asyncio fastapi event-loop
1个回答
0
投票

使用这个库是因为没有异步模拟吗?

我不知道异步模拟是否存在。但我不同意@MatsLindh 的观点,认为 id 没有意义。如果这个操作比较繁重,需要很长时间,那么最好插入一些

await asyncio.sleep(0)
,让解释器切换到其他任务,避免长时间阻塞事件循环。

循环阻塞会对应用程序的性能产生多大影响?

取决于所选算法。但我认为不会产生太大的影响。

同时使用同步和异步代码的接受程度如何? 地方?会有什么缺点?这可以做还是应该做 避免吗?

如果这个同步函数没有任何 IO 绑定操作并且不是很“重”,那么就可以了。缺点是在执行异步协程内的同步代码时,所有其他任务都会被冻结。但是,就像我说的,如果这个功能不是很重的话,问题也不大。

如果您使用重型算法来哈希密码并希望避免这些阻塞,您可以在线程池中运行此同步函数:

#from starlette.concurrency import run_in_threadpool

password_verified = await run_in_threadpool(verify_password, password, user.hashed_password)
© www.soinside.com 2019 - 2024. All rights reserved.