这是文档中的代码:
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)是同步的。在异步端点中。因此,事件循环将阻塞,循环将无法将控制权转移给另一个任务。
对此,我有几个疑问:
使用这个库是因为没有异步模拟吗?
我不知道异步模拟是否存在。但我不同意@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)