简体   繁体   English

Python Tornado - 异步请求被阻塞

[英]Python Tornado - Asynchronous Request is blocking

The request handlers are as follows:请求处理程序如下:

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()

When I GET localhost:8888/test , the page loads 10 seconds and shows Awake after 10 seconds ;当我 GET localhost:8888/test ,页面加载 10 秒并Awake after 10 seconds显示Awake after 10 seconds while it is loading, if I open localhost:8888/index in a new browser tab, the new index page is not blocked and loaded instantly.在加载时,如果我在新的浏览器选项卡中打开localhost:8888/index ,新的索引页面不会被阻止并立即加载。 These fit my expectation.这些符合我的预期。

However, while the /test is loading, if I open another /test in a new browser tab, it is blocked.但是,在加载/test ,如果我在新的浏览器选项卡中打开另一个/test ,它会被阻止。 The second /test only starts processing after the first has finished.第二个/test仅在第一个完成后才开始处理。

What mistakes have I made here?我在这里犯了什么错误?

What you are seeing is actually a browser limitation, not an issue with your code.您所看到的实际上是浏览器限制,而不是您的代码问题。 I added some extra logging to your TestHandler to make this clear:我在您的TestHandler添加了一些额外的日志记录以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()

If I open two curl sessions to localhost/test simultaneously, I get this on the server side:如果我同时打开两个 curl 会话到 localhost/test,我会在服务器端得到这个:

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

And this on the client side:这在客户端:

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

Which is exactly what you expect.这正是您所期望的。 However in Chromium, I get the same behavior as you.但是在 Chromium 中,我的行为与您相同。 I think that Chromium (perhaps all browsers) will only allow one connection at a time to be opened to the same URL.我认为 Chromium(可能是所有浏览器)一次只允许打开一个连接到同一个 URL。 I confirmed this by making IndexHandler run the same code as TestHandler , except with slightly different log messages.我通过让IndexHandler运行与IndexHandler相同的代码来确认这TestHandler ,除了日志消息略有不同。 Here's the output when opening two browser windows, one to /test , and one to /index :这是打开两个浏览器窗口时的输出,一个到/test ,一个到/index

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

As you can see both ran concurrently without issue.如您所见,两者同时运行都没有问题。

I think you picked the "wrong" test for checking parallel GET requests, that's because you're using a blocking function for your test: time.sleep() , which its behavior doesn't really occur when you simply render an HTML page ...我认为您选择了“错误”的测试来检查并行GET请求,那是因为您在测试中使用了阻塞函数: time.sleep() ,当您简单地呈现 HTML 页面时,它的行为不会真正发生。 ..

What happens is, that the def get() ( which handle all GET requests ) is actually being blocked when you use time.sleep it cannot process any new GET requests, puts them in some kind of "queue".发生的情况是, def get() (处理所有 GET 请求)实际上在您使用time.sleep时被阻塞,它无法处理任何新的 GET 请求,将它们放入某种“队列”中。

So if you really want to test sleep() - use the Tornado non-blocking function: tornado.gen.sleep()所以如果你真的想测试sleep() - 使用 Tornado非阻塞函数: tornado.gen.sleep()

Example:例子:

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")

Open multiple tabs in your browser, then you'll see that all requests are being processed when they arrive w/o "queueing" the new requests that comes in ..在浏览器中打开多个选项卡,然后您会看到所有请求在到达时都在被处理,而没有“排队”进来的新请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM