我使用aiohttp
编写了一个基本的REST API,下面包含了一个简化版本来说明我想要解决的问题。
API有两个端点 - 每个端点都调用一个执行某些计算的函数。两者之间的区别在于,对于其中一个端点,计算需要10秒,而另一个端点只需1秒。
我的代码如下(实际计算已被time.sleep()
调用替换)。
import time
from aiohttp import web
def simple_calcs():
time.sleep(1) # Pretend this is the simple calculations
return {'test': 123}
def complex_calcs():
time.sleep(10) # Pretend this is the complex calculations
return {'test': 456}
routes = web.RouteTableDef()
@routes.get('/simple_calcs')
async def simple_calcs_handler(request):
results = simple_calcs()
return web.json_response(results)
@routes.get('/complex_calcs')
async def complex_calcs_handler(request):
results = complex_calcs()
return web.json_response(results)
app = web.Application()
app.add_routes(routes)
web.run_app(app)
我想发生什么:
如果我向较慢的端点发送请求,然后立即向更快的端点发送请求,我希望首先从较快的端点收到响应,而较慢的计算仍在进行中。
实际发生了什么:
由较慢端点执行的计算是阻塞的。我在~10秒后从慢速终点接收响应,在~11秒后从快速终点接收响应。
我花了最后几个小时绕圈子,阅读asyncio
和multiprocessing
,但无法找到任何可以解决我问题的东西。可能我需要花更长的时间来研究这个领域以获得更好的理解,但希望我能够朝着正确的方向努力实现预期的结果。
在asyncio中应该避免任何阻塞IO调用。
基本上time.sleep(10)
阻止整个aiohttp服务器10秒。
要解决它,请使用loop.run_in_executor()电话:
async def complex_calcs():
loop = asyncio.get_event_loop()
loop.run_in_executor(None, time.sleep, 10) # Pretend this is the complex calculations
return {'test': 456}