Synchronous v / s Asynchronous

I am trying to understand the basic example presented on the tornado documentation introduction page. It has 2 blocks of code. Synchronous suits me, and I understand that. But asynchronous is one that I cannot understand.

Synchronous

from tornado.httpclient import HTTPClient def synchronous_fetch(url): http_client = HTTPClient() response = http_client.fetch(url) return response.body 

Asynchronous

 from tornado.httpclient import AsyncHTTPClient def asynchronous_fetch(url, callback): http_client = AsyncHTTPClient() def handle_response(response): callback(response.body) http_client.fetch(url, callback=handle_response) 

If you can provide a better example, do it.

+6
source share
1 answer

The idea of ​​asynchronous calls is something that works in almost all web programming ... "stuff" (frameworks, servers, libraries ...) is not only the concept of a Tornado web server.

Main idea:

  • With a synchronous request, you make a request and stop executing your program until you receive a response from the HTTP server (or an error if the server cannot be reached, or a timeout if the interrupt occurs is too long to respond) The interpreter is blocked until until the request is completed (until you get a final answer to what happened with the request: everything went well? was there an error? timeout? ...).
  • In asynchronous requests, you run the request and you forget about it, which means: the interpreter continues to execute the code after the request is made without waiting for the request to be completed.

    It seems ... pretty pointless, right? Do you send the request “into the void of space” and continue execution as usual? What happens when the server sends you a response? I made a request, and I want to know what happened to him! Otherwise, I would not have typed this in my code to start with!

    Well, here where the callback comes. You run the request "into the void of space" BUT , you provide a callback function, so when the HTTP server at the other end sends you a response, this function is launched with the specified response as the first argument.

Take a look at this with an example.

I created a very simple Tornado server (using Python 2.7 and Tornado 4.2 ) with only one handler. On a GET it takes 5 seconds to return. I did this with time.sleep , but in real life it can be a very time-consuming process (access to the database, performing some calculations ... who knows? ...)

Here's the server file (based on that given in the Tornado documentation):

SampleServer.py :

 #!/usr/bin/env python2.7 import time import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): print "Someone is GET'ing me" time.sleep(5) self.write("Hello, world") application = tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": application.listen(8888) print "Starting sample server." tornado.ioloop.IOLoop.current().start() 

Open a terminal and run this code to have a server. You will receive Tornado listening on port 8888 your local machine.

Now create another script (which you will need to run on a different terminal), which GET http://localhost:8888 two ways: first synchronously and then asynchronously.

SampleFetcher.py :

 #!/usr/bin/env python2.7 import datetime import tornado.ioloop from tornado.httpclient import HTTPClient, AsyncHTTPClient def HUMAN_DT_NOW(): return datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") def synchronous_fetch(url): http_client = HTTPClient() start_dt = datetime.datetime.now() response = http_client.fetch(url) end_dt = datetime.datetime.now() print ("The synchronous fetch took %s seconds." % (end_dt - start_dt).total_seconds()) print "(Sync) Server said: \"%s\"" % response.body def asynchronous_fetch(url): http_client = AsyncHTTPClient() def handle_response(response): print "" print "Yawwza... Finally!!!." print "The time now is %s" % HUMAN_DT_NOW() print "(Async) Server said: \"%s\"" % response.body print "Gonna launch a 'fetch' to the universe at %s..." % HUMAN_DT_NOW() http_client.fetch(url, callback=handle_response) if __name__ == "__main__": print " ------ Synchronous ------ " print ("Starting synchronous fetch at %s." " The program will block for about 5 secs." % HUMAN_DT_NOW()) synchronous_fetch('http://localhost:8888') print "Pfew! That was a lot of wait time!!. I got bored watching my terminal" print "" print "Aight, let see what Asynchronous can do" print " ------ Asynchronous ------ " asynchronous_fetch('http://localhost:8888') print "You're gonna see this line before the \"Yawwza...\" one" print "This one too. Now is %s" % HUMAN_DT_NOW() # The IOLoop below is required to prevent the script from closing ahead # of time, but allowing Asynchronous interactions tornado.ioloop.IOLoop.current().start() 

This will output:

 Starting synchronous fetch at 2015/07/04 13:25:47. The program will block for about 5 secs. The synchronous fetch took 5.009597 seconds. (Sync) Server said: "Hello, world" Pfew! That was a lot of wait time!!. I got bored watching my terminal Aight, let see what Asynchronous can do ------ Asynchronous ------ Gonna launch a 'fetch' to the universe at 2015/07/04 13:25:52... You're gonna see this line before the "Yawwza..." one This one too. Now is 2015/07/04 13:25:52 Yawwza... Finally!!!. The time now is 2015/07/04 13:25:57 (Async) Server said: "Hello, world" 

Focus on the asynchronous part, here:

  ------ Asynchronous ------ Gonna launch a 'fetch' to the universe at 2015/07/04 13:25:52... You're gonna see this line before the "Yawwza..." one This one too. Now is 2015/07/04 13:25:52 Yawwza... Finally!!!. The time now is 2015/07/04 13:25:57 (Async) Server said: "Hello, world" 

If you see, the script did asynchronous_fetch at 13:25:52 , but immediately (in the same second), the interpreter continued to execute and ran the following statements after the request (lines that print You're gonna see this line before the "Yawwza..." one and This one too. Now is 2015/07/04 13:25:52 ).

Then, after about 5 seconds, the server answered, and the callback function (which was handle_response ) was handle_response , and when you see

 Yawwza... Finally!!!. The time now is 2015/07/04 13:25:57 

Hope this helps a little to understand the idea. This is a very useful concept, and this applies not only to tornadoes.

Feel free to play with the two provided script examples, change the material, increase the time that the server receives for an answer ...

Further recommended reading:

+16
source

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


All Articles