In Tornado\'s chat demo, it has a method like this:
@tornado.web.asynchronous
def post(self):
cursor = self.get_argument("cursor", None)
gl
The problem with the code in original question is that when you call time.sleep(4)
you are effectively blocking the execution of event loop for 4 seconds. And accepted answer doesn't solve the problem either (IMHO).
Asynchronous serving in Tornado works on trust. Tornado will call your functions whenever something happens, but it trusts you that you will return control to it as soon as possible. If you block with time.sleep()
then this trust is breached - Tornado can't handle new connections.
Using multiple threads only hides the mistake; running Tornado with thousands of threads (so you can serve 1000s of connections simultaneously) would be very inefficient. The appropriate way is running a single thread which only blocks inside Tornado (on select
or whatever Tornado's way of listening for events is) - not on your code (to be exact: never on your code).
The proper solution is to just return from get(self)
right before time.sleep()
(without calling self.finish()
), like this:
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
print("Starting")
You must of course remember that this request is still open and call write()
and finish()
on it later.
I suggest you take a look at chat demo. Once you strip out the authentication you get a very nice example of async long polling server.