使用FastAPI等异步框架开发接口时,如果接口实现逻辑中有大量阻塞任务,会阻塞loop调度,大大影响服务性能,甚至还不如传统多线程框架(tomcat)!
可以使用asyncio.to_thread包装下阻塞方法,防止阻塞当前调度。
测试:
import asyncio
import time# a blocking io-bound task
def blocking_task():time.sleep(2)print('Blocking task success')return 1# 使用asyncio库来执行异步操作,以模拟一个异步任务的完成过程。
async def async_task():await asyncio.sleep(1)print('Async task success')return 1# main coroutine
async def main():# 先创建并开启阻塞任务block_tasks = [asyncio.create_task(asyncio.to_thread(blocking_task)) for _ in range(100)]# 后创建并开启异步任务async_tasks = [asyncio.create_task(async_task()) for _ in range(100)]# 等待异步任务执行完成await asyncio.gather(*async_tasks)# 等待阻塞任务执行完成rets = await asyncio.gather(*block_tasks)return sum(rets)start_time = time.time()
ret = asyncio.run(main())
print(f'ret:{ret}, time: {time.time() - start_time}')
执行日志:
可以看到异步任务并没有等待阻塞任务。
参考文档:https://zhuanlan.zhihu.com/p/610881194