tornado是一个异步Web服务器吗?

2024-07-05 14:10:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习编写一个可以处理数千个连接的后端服务器。在

我查看了一些示例代码,但发现它仍然是以同步逻辑编写的。在

例如:(take fromhttp://www.tornadoweb.org/en/stable/gen.html

@gen.coroutine
def get(self):
    http_client = AsyncHTTPClient()
    response1, response2 = yield [http_client.fetch(url1), http_client.fetch(url2)]
    print(response1.body, response2.body)

很明显,print语句在得到两个回迁的响应之前无法执行,否则它将由于访问不存在的数据而引发异常。在

因此,它在最后两行之间必须有一个,但是对于非块、异步、事件驱动的情况,不是tornado是高亮显示的。。。然后,可以处理数千个连接?在


Tags: 代码服务器clienthttp示例wwwbodyfetch
2条回答

是的!在

在长时间运行的作业和缓慢的IO操作之间使用yield和{}这两种不同的模式很可能会混淆。我刚刚在那件事上犯了一个严重的错误。在

  • 在长期运行的工作中

    1. 它的生成器的next()方法被反复调用,并且每次都执行一个工作单元。在
    2. 如果有多个coroutine在运行,调度程序将逐个调用每个next()方法,以便在两个作业之间共享CPU时间。因此它是作业之间的协作,因此称为coroutine。在
  • 在慢IO操作中

    1. 对每个next()点只调用一次next()方法。在
    2. 一旦yield从执行IO操作开始,IO操作就委托给操作系统内核。当IO操作完成时,调度程序将添加一个回调,它将调用next()方法。在
    3. 现在调度程序的问题是何时调用next()方法。这是由操作系统级的异步特性提供支持的,比如在IO完成时,epollIOCP到notiy调度器。在
    4. 所以整个流程是,运行到生成IO的点,而不是yield来移交执行。IO完成后,它将通过从调度程序调用next()继续执行。在
    5. 此控制流的效果与回调模式完全相同,两者都是
      • 跑向一个点东爱
      • 移交执行,以便流程可以执行其他工作
      • IO已完成,继续运行。在
      • 唯一的区别是一个是继续执行前一个函数,另一个继续执行一个新的回调函数。在

因此,总而言之:

  • 在长时间运行的作业中,一旦进程空闲,调度程序将调用每个next()方法

  • 在慢IO操作中,next()方法在IO操作完成后只调用一次

我想如果你意识到这一点,你就会明白使用yield和{}实际上可以与{}具有相同的能力。在

是,tornado是异步的。您展示的示例是一个^{};它实际上是非阻塞的,并在yield调用时将控制释放回tornado事件循环。控件只在两个http_client.fetch调用实际完成时返回get函数。在

这两个例子实际上在tornado中功能等效:

class AsyncHandler(RequestHandler):
    @asynchronous
    def get(self):
        http_client = AsyncHTTPClient()
        http_client.fetch("http://example.com",
                          callback=self.on_fetch)

    def on_fetch(self, response):
        do_something_with_response(response)
        self.render("template.html")

还有一个协同程序版本:

^{pr2}$

协同程序允许您编写异步代码,它看起来是同步的,可读性更强。当上面的代码命中yieldget将挂起并将http_client.fetch返回给gen.coroutine装饰器的^{}对象。gen.coroutine修饰符有魔力,它可以安排fetch调用返回的Future的结果,以便在准备就绪后将其传递回get。在

相关问题 更多 >