Python Tornado - 异步请求阻塞

时间:2014-06-08 13:12:05

标签: python asynchronous tornado

请求处理程序如下:

class TestHandler(tornado.web.RequestHandler):    #  localhost:8888/test
    @tornado.web.asynchronous
    def get(self):
        t = threading.Thread(target = self.newThread)
        t.start()

    def newThread(self):
        print "new thread called, sleeping"
        time.sleep(10)
        self.write("Awake after 10 seconds!")
        self.finish()

class IndexHandler(tornado.web.RequestHandler):           #   localhost:8888/ 
    def get(self):
        self.write("It is not blocked!")
        self.finish()

当我获取localhost:8888/test时,页面加载10秒并显示Awake after 10 seconds;在加载时,如果我在新的浏览器选项卡中打开localhost:8888/index,则不会立即阻止和加载新的索引页面。这些符合我的期望。

但是,在加载/test时,如果我在新的浏览器标签中打开另一个/test,则会被阻止。第二个/test仅在第一个完成后开始处理。

我在这里犯了什么错误?

2 个答案:

答案 0 :(得分:7)

您所看到的实际上是浏览器限制,而不是代码问题。我在TestHandler添加了一些额外的日志记录,以明确这一点:

class TestHandler(tornado.web.RequestHandler):    #  localhost:8888/test
    @tornado.web.asynchronous
    def get(self):
        print "Thread starting %s" % time.time()
        t = threading.Thread(target = self.newThread)
        t.start()

    def newThread(self):
        print "new thread called, sleeping %s" % time.time()
        time.sleep(10)
        self.write("Awake after 10 seconds!" % time.time())
        self.finish()

如果我同时打开两个curl会话到localhost / test,我会在服务器端得到这个:

Thread starting 1402236952.17
new thread called, sleeping 1402236952.17
Thread starting 1402236953.21
new thread called, sleeping 1402236953.21

这在客户端:

Awake after 10 seconds! 1402236962.18
Awake after 10 seconds! 1402236963.22

这正是您所期望的。但是在Chromium中,我得到了与你相同的行为。我认为Chromium(可能是所有浏览器)一次只允许一个连接打开到同一个URL。我通过使IndexHandler运行与TestHandler相同的代码来确认这一点,除了略有不同的日志消息。这是打开两个浏览器窗口时的输出,一个到/test,一个到/index

index Thread starting 1402237590.03
index new thread called, sleeping 1402237590.03
Thread starting 1402237592.19
new thread called, sleeping 1402237592.19

正如你所看到的那样,两者同时没有问题。

答案 1 :(得分:0)

我认为您选择了“错误”测试来检查并行的GET请求,这是因为您在测试中使用了 blocking 功能:time.sleep(),当您仅呈现HTML页面时,行为并不会真正发生...

发生的事情是,当您使用def get()time.sleep(处理所有GET请求)实际上被阻止了,它无法处理任何新的GET请求,从而将它们放入某种“队列”中

因此,如果您真的想测试sleep()-使用龙卷风无阻塞函数:tornado.gen.sleep()

示例:

from tornado import gen

@gen.coroutine
def get(self):        
    yield self.time_wait()       

@gen.coroutine
def time_wait(self):
    yield gen.sleep(15)
    self.write("done")

在浏览器中打开多个标签,然后您会看到所有请求到达时都在处理中,而不会“排队”出现在其中的新请求。