所以我理解Tornado本身是非阻塞事件循环I / O的基本思想,但阻止IO操作(如数据库访问)会导致Tornado在这些操作期间阻塞。
我不明白为什么看起来Tornado在非阻塞操作期间会阻塞。
我在处理程序中有以下代码:
class MyHandler(BaseHandler):
def get(self):
x = 0
for i in xrange(0,500000000):
x = i
self.render("page_temp.html",
title="Page"
)
加载页面大约需要20秒。如果我打开另一个浏览器窗口并尝试加载任何其他页面,我会挂起,直到20秒页面加载。可能是因为这两个请求来自同一个用户吗?
答案 0 :(得分:4)
您正在处理程序中直接进行长时间的CPU操作。 tornado
是单线程的,这意味着它不能在事件循环线程中执行CPU绑定工作,而不会阻止所有其他请求。如果您需要执行CPU绑定工作,则必须在后台线程或进程中执行此操作。
为了使此方法同时处理请求,它需要如下所示:
from concurrent.futures import ThreadPoolExecutor
from tornado import gen
from tornado.web import RequestHandler
executor = ThreadPoolExecutor(8) # 8 Threads in the pool
class ThreadPoolHandler(RequestHandler):
def _do_loop(self):
x = 0
for i in xrange(0,500000000):
x = i
@gen.coroutine
def get(self):
yield executor.submit(self._do_loop) # Run through the loop without blocking tornado
self.render("page_temp.html",
title="Page"
)
通过使用ThreadPoolExecutor
在后台线程中运行昂贵的for循环,tornado
可以在等待CPU工作完成时继续提供其他请求。