同步 v/s 异步 [英] Synchronous v/s Asynchronous

查看:23
本文介绍了同步 v/s 异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解 tornado 文档介绍页面上提供的基本示例.它有2个代码块.Synchronous 对我来说很好,我确实理解.但异步是我无法理解的.

I am trying to understand the basic example provided on the introduction page of tornado documentation. It has 2 blocks of code. The Synchronous one is fine for me, and I do understand it. But the asynchronous one is one I am not able to understand.

同步

from tornado.httpclient import HTTPClient

def synchronous_fetch(url):
    http_client = HTTPClient()
    response = http_client.fetch(url)
    return response.body

异步

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 with a better example, please do so.

推荐答案

异步 调用的想法在许多 Web 相关编程中的工作原理几乎相同......东西(框架、服务器、库...)不仅仅是来自 Tornado 网络服务器的概念.

The idea of asynchronous calls is something that works pretty much the same in many web related programming... "stuff" (frameworks, servers, libraries...) Is not only a concept from the Tornado web server.

基本思想是:

  • 在 s̲y̲n̲c̲h̲r̲o̲n̲o̲u̲s̲ 请求中,您发出请求并停止执行您的程序,直到您收到来自 HTTP 服务器的响应(或者如果服务器无法访问则出现错误,或者如果服务器正在占用则超时,方式回复太长)解释器被阻塞,直到请求完成(直到你得到关于请求发生了什么的明确答案:是否顺利?是否有错误?超时?... ).
  • 在a̲s̲y̲n̲c̲h̲r̲o̲n̲o̲u̲s̲请求时,你启动"请求,你有点忘记它",意思是:解释器在之后继续执行代码无需等待请求完成即可发出请求.

  • On a s̲y̲n̲c̲h̲r̲o̲n̲o̲u̲s̲ request, you make the request and stop executing your program until you get a response from the HTTP server (or an error if the server can't be reached, or a timeout if the sever is taking way, way too long to reply) The interpreter is blocked until the request is completed (until you got a definitive answer of what happened with the request: did it go well? was there an error? a timeout?... ).
  • On a̲s̲y̲n̲c̲h̲r̲o̲n̲o̲u̲s̲ requests, you "launch" the request, and you kind of "forget about it", meaning: The interpreter continues executing the code after the request is made without waiting for the request to be completed.

这似乎……毫无意义,对吧?你发送请求到空白处",然后像往常一样继续执行?当服务器向您发送响应时会发生什么?我提出了一个请求,我想知道它发生了什么!否则,我就不会在我的代码中输入它!

This seems... rather pointless, right? You send the request "to the void of space", and continue executing as usual? What happens when the server sends you its response? I made a request, and I wanna know what happened to it! Otherwise, I wouldn't have typed that in my code to begin with!!

好吧,这就是 callback 的用武之地.您向 to the void of space"发起请求 但是您提供了一个回调函数因此,当另一端的 HTTP 服务器向您发送响应时,该函数将使用 response 作为第一个参数运行.

Well, here's where the callback comes in. You launch the request "to the void of space" BUT you provide a callback function so when the HTTP server on the other end sends you its response, that function is run with said response as the first argument.

让我们用一个例子来看看.

Let's see it with a en example.

我创建了一个非常简单的 Tornado 服务器(使用 Python 2.7Tornado 4.2),只有一个处理程序.在 GET 上,返回需要 5 秒.我已经用 time.sleep 做到了这一点,但在在现实生活中,这可能是一个非常耗时的过程(访问数据库,执行一些计算......谁知道?......)

I've 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've done that with a time.sleep, but in real life, it could be a very time consuming process (access a database, perform some calculations... who knows?...)

这是服务器文件(基于 Tornado 中提供的示例文档):

Here's the server file (based on the example provided in the Tornado documentation):

#!/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()

打开一个终端并运行该代码以获得一个服务器.你会得到一个 Tornado 监听你本地机器的 8888 端口.

Open a terminal and run that code to have a server. You'll get a Tornado listening on port 8888 of your local machine.

现在,让我们以两种方式创建另一个脚本(您必须在另一个终端中运行)它 GETs http://localhost:8888:首先同步然后异步.

Now, let's create another script (which you'll have to run in another terminal) that GETs http://localhost:8888 in two ways: First synchronously and then asynchronously.

#!/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's 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()

这将输出:

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's 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"

让我们关注异步部分,这里:

Let's 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"

如果您看到,脚本在 13:25:52 生成了 asynchronous_fetch,但是立即(在同一秒内),解释器继续执行,并在发出请求后运行下一个语句(打印 You're going to see this line before the "Yawwza..." one and This one too.现在是 2015/07/04 13:25:52).

If you see, the script made the asynchronous_fetch at 13:25:52, but immediately (in the same second), the interpreter continued executing, and run the next statements after the request was made (the 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 ).

然后,大约 5 秒后,服务器响应,并且执行了 callback 函数(即 handle_response),然后你就会看到

Then, around 5 seconds later, the server responded, and the callback function (which was handle_response) was executed, and that's when you see

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

我希望这有助于理解这个想法.这是一个非常有用的概念,它不仅适用于 Tornado.

I hope this helped understanding the idea a bit. It's a very useful concept, and it doesn't only apply to Tornado.

随意使用提供的两个示例脚本,更改内容,增加服务器回复的时间......

Feel free to play with the two sample scripts provided, change stuff, increase the times it gets for the server to reply...

进一步推荐阅读:

这篇关于同步 v/s 异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆