Tornado RequestHandler可以在等待Future完成时参与请求吗?

时间:2015-02-28 23:12:28

标签: tornado nonblocking coroutine requesthandler concurrent.futures

单个Tornado RequestHandler课可以在等待Future完成其中一个实例的同时参加新请求吗?

我正在调试一个调用ThreadPoolExecutor的Tornado协程,我注意到,当协同程序正在等待执行程序完成时,RequestHandler被阻止了。所以对这个处理程序的任何新请求都在等待协程完成。

以下是我为重现观察而编写的代码:

from time import sleep
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import Application, RequestHandler
from tornado.gen import coroutine

class Handler1(RequestHandler):
    @coroutine
    def get(self):
        print('Setting up executor ...')
        thread_pool = ThreadPoolExecutor(1)

        print('Yielding ...')
        yield thread_pool.submit(sleep, 30)

        self.write('Ready!')
        print('Finished!')

app = Application([('/1$', Handler1)])
app.listen(8888)
PeriodicCallback(lambda: print('##'), 10000).start()
IOLoop.instance().start()

现在,如果我访问localhost:8888/1两次,我会得到以下输出:

##
Setting up executor ...
Yielding ...
##
##
##
Finished!
Setting up executor ...
Yielding ...
##
##
##
Finished!
##

但我希望会发生以下情况:

##
Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
##
##
##
Finished!
Finished!
##

请注意,只有RequestHandler似乎被阻止,因为我们仍然每隔10秒获得##。实际上,如果您添加另一个相同的RequestHandler(处理程序2),并且您访问localhost:8888/1localhost:8888/2,则会产生预期的输出。

这是正常的吗?这是预期的行为吗?

抱歉我的英语不好。

2 个答案:

答案 0 :(得分:3)

Tornado为每个新请求创建RequestHandler的 new 实例。所以你的代码确实表现得像你期望的那样。我运行它并打开两个终端窗口,每个窗口都运行wget localhost:8888/1。您的代码打印:

Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
##
##
##
Finished!
Finished!

如你所料。你可能看到的是你的浏览器不愿意一次打开两个到同一URL的连接。实际上,如果我打开两个标签并尝试在两者中加载“localhost:8888/1”,我可以重现你用chrome看到的“阻塞”行为。但是,如果我修改你的代码:

app = Application([
    ('/1$', Handler1),
    ('/2$', Handler1)])

在Chrome中的两个标签中打开“localhost:8888/1”和“localhost:8888/2”,我看到它会同时打开两个连接。

尝试wget测试,不受浏览器干扰。

答案 1 :(得分:1)

对我也有用:

$ curl http://127.0.0.1:8888/1 &
[1] 95055
$ curl http://127.0.0.1:8888/1 &
[2] 95056
$ curl http://127.0.0.1:8888/1 &
[3] 95057

龙卷风计划输出:

bash-3.2$ python3 test.py 
##
##
Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
##
##
##
Finished!
Finished!
Finished!
##
##
##