Python Tornado - asynchronous request blocks

Request handlers look like this:

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 ; while it loads, if I open localhost:8888/index in a new browser tab, the new index page does not block and does not load instantly. They meet my expectations.

However, when loading /test , if I open another /test in a new browser tab, it is blocked. The second /test starts processing only after the first is completed.

What mistakes have I made here?

+7
source share
2 answers

What you see is actually a browser limitation, not a problem with your code. I have added some additional protocols to your TestHandler so that this becomes clear:

 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 simultaneously open two curl sessions for localhost / test, I get this on the server side:

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

And this is on the client side:

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

This is exactly what you expect. However, in Chromium, I get the same behavior as you. I think that Chromium (possibly all browsers) will only allow one connection to open one URL at a time. I confirmed this by doing IndexHandler running the same code as TestHandler , with the exception of a few different log messages. Here's the output when opening two browser windows, one on /test and one on /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 started simultaneously without any problems.

+7
source

I think you chose the β€œwrong” test for checking concurrent GET requests because you are using a blocking function for your test: time.sleep() , whose behavior does not actually occur when you simply render the HTML page ...

What happens is that def get() (which processes all GET requests) is actually blocked when you use time.sleep it cannot process any new GET requests, puts them in a kind of "queue".

So if you really want to check sleep() , use the non-blocking Tornado function: 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 several tabs in your browser, and you will see that all requests are processed when they arrive, without "queues" of new incoming requests.

0
source

Source: https://habr.com/ru/post/970536/


All Articles