我正在尝试编写一个在某些请求处理程序中使用sqlalchemy的龙卷风Web应用程序。这些处理程序有两个部分:一个需要很长时间才能完成,另一个则使用sqlalchemy并且相对较快。 我想使请求的慢速部分异步,而不是sqlalchemy部分。我可以执行以下代码并安全吗?
class ExampleHandler(BaseHandler):
async def post(self):
loop = asyncio.get_event_loop()
await loop.run_in_executor(...) # very slow (no sqlalchemy here)
with self.db_session() as s: # sqlalchemy session
s.add(...)
s.commit()
self.render(...)
这个想法是让sqlalchemy仍然阻塞,但计算量大的部分不阻塞应用程序。
答案 0 :(得分:3)
龙卷风Web服务器使用异步代码来绕过python Global Interpreter Lock的限制。众所周知,GIL只允许一个执行线程在python解释器进程中发生。由于使用了事件循环,龙卷风能够同时回答许多请求。事件循环一次可以执行一个小任务。让我们让您自己的帖子处理程序更好地理解这一点。
在此处理程序中,当python解释器获取到await关键字时,它将暂停函数的执行并将其排队,以供稍后在事件循环中使用。然后,它检查事件循环以响应可能已排队的其他事件,例如响应新连接或为另一个处理程序提供服务。
当您阻塞异步函数时,由于无法暂停您的函数并为其他服务提供服务,因此冻结了整个事件循环。这实际上对您而言意味着,在异步功能被阻止时,您的Web服务器将不接受或处理任何请求。好像您的Web服务器正在挂起并且确实卡住了。
要保持服务器的响应速度,您必须找到一种以异步非阻塞方式执行sqlalchemy查询的方法。