浅谈FastAPI到底用不用async问题
作者:程序员的战歌
这篇文章主要介绍了FastAPI到底用不用async问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
FastAPI到底用不用async
FastAPI的很快,归功于它的异步处理。
那我们用FastAPI框架时,函数到底用不用async模式?
官方文档:
https://fastapi.tiangolo.com/async/
做个实验
from fastapi import APIRouter import time import asyncio router = APIRouter() @router.get("/a") async def a(): time.sleep(1) return {"message": "异步模式,但是同步执行sleep函数,执行过程是串行的"} @router.get("/b") async def b(): loop = asyncio.get_event_loop() await loop.run_in_executor(None, time.sleep, 1) return {"message": "线程池中运行sleep函数"} @router.get("/c") async def c(): await asyncio.sleep(1) return {"message": "异步模式,且异步执行sleep函数"} @router.get("/d") def d(): time.sleep(1) return {"message": "同步模式,但是FastAPI会放在线程池中运行,所以很快"}
我们并发100个请求分别测试这4个接口。
结果
- /a接口:100秒
- /b接口:1秒
- /c接口:1秒
- /d接口:3秒
/a接口
- fastapi框架会将async函数会放到event loop中运行。
- 虽然使用了async,但是函数内部并没有用到await,所以堵塞了。
- 执行过程是串行的,所以总耗时100秒。
/b接口
- 利用asyncio异步IO获取当前的event loop。
- 然后将time.sleep(1)放到一个event loop中去运行,函数内部用到了await,所以无堵塞。
- 执行过程是并行的,所以总耗时1秒。
/c接口
- 使用异步IO的sleep取代了普通的同步sleep。
- 原理与/b接口一致。
- 执行过程是并行的,所以总耗时1秒。
/d接口
- 这个函数没有async修饰,即一个普通函数。
- 但是FastAPI会将函数放到thread pool中执行。
- 服务器是8核CPU,线程池的默认配置是核心数*5=40。
- 服务器在第一秒和第二秒分别处理40个请求,第三秒处理20个请求。
- 所以100个并发总耗时3秒。
总结
官方说,无论你是否使用async,FastAPI都会采用异步的方式处理。
但是,如果你定义了async函数,函数体却是同步的调用(例:/a接口),将导致函数执行过程变成串行。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。