使用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