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
; 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. These fit my expectation.
However, while the /test
is loading, if I open another /test
in a new browser tab, it is blocked. The second /test
only starts processing after the first has finished.
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:
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:
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. I think that Chromium (perhaps all browsers) will only allow one connection at a time to be opened to the same URL. I confirmed this by making IndexHandler
run the same code as TestHandler
, except with slightly different log messages. Here's the output when opening two browser windows, one to /test
, and one to /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 ...
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".
So if you really want to test sleep()
- use the Tornado non-blocking 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 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 ..