• tornado 学习笔记4 异步以及非阻塞的I/O


           Read-time(实时)的网站需要针对每个用户保持长时间的连接。在传统的同步网站服务中,通常针对每个用户开启来一个线程来实现,但是这样做非常昂贵。

           为了使并发连接的成本最小化,Tornada使用单个线程事件循环机制。这样意味着所有的的应用程序的目标都是异步且非阻塞的,因为在同一事件只有一个线程是活动的。

           异步和非阻塞非常相近而且经常可交换使用,但是他们确实不是一个东西。

    4.1 阻塞

           函数阻塞时,这个函数会一直等待处理的结果返回。一个函数会因为多种情况阻塞,比如网络I/O,硬盘I/O等等。事实上,每一个函数都会阻塞,最少是一点点,因为他们在运行而且要使用Cpu(最有代表性的是密码hash函数bcrypt,要使用cpu的毫秒时间)。

           一个函数在一些情况下会阻塞,但是在另外一些情况下不会阻塞。举个例子来说,tornado.httpclient 在DNS解决方案下,当采取默认的配置时会阻塞,但是在其他网络访问的情况下不会阻塞(比如使用ThreadedResolver 或者tornado.curl_httpclient)。

    4.2 异步

            一个异步的函数在函数结束之前就可以返回,通常在触发一些未来的动作之前会引起后台处理处理一些工作。下面有几种异步接口:

    • Callback 参数(回调函数)
    • 返回一个占位符(比如Future、Promise、Deferred)
    • 发送至一个队列中(Queue)
    • 回调注册(POSIX signals)

         示例:

          下面是一段同步函数的示例。

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

          下面是用带有CallBack参数重写的异步函数,实现同一功能。

    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)

          

            而用Future来替代回调的实现如下

    from tornado.concurrent import Future
    
    def async_fetch_future(url):
        http_client = AsyncHTTPClient()
        my_future = Future()
        fetch_future = http_client.fetch(url)
        fetch_future.add_done_callback(
            lambda f: my_future.set_result(f.result()))
        return my_future

            但是,原生的Future版本更复杂,但是Tornado用Futures作为推荐的最佳实践方式,因为Futures用两大主要的优点。其一,错误处理表现更加一致,因为Future.result方法只能简单地触发一个异常。其二,Futures在并发环境中更好使用。下面是我们上面示例函数的并发版本,非常像最初的同步函数的版本。

    from tornado import gen
    
    @gen.coroutine
    def fetch_coroutine(url):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch(url)
        raise gen.Return(response.body)

            raise gen.Return(response.body) 这条语句是Python 2(及3.2)的实现方式,但是生成器不允许返回值。为了克服这个问题,Tornado coroutine返回一种特别类型的异常,叫Return。Coroutine捕获这个异常而且把它当成一个返回值。在Python 3.3版本以上,语句return response.body达到同一的结果。

  • 相关阅读:
    java 接口和抽象类的一个最大的区别
    python 简化数据结构的初始化二 支持关键字参数
    python 简化数据结构的初始化一
    python @staticmethod
    python @classmethod
    codeskulptor hosts
    An Introduction to Interactive Programming in Python (Part 1) -- Week 2_2 练习
    An Introduction to Interactive Programming in Python (Part 1) -- Week 2_1 练习
    mysql-5.7.14-winx64免安装版在win10下的详细配置过程
    python 反模式
  • 原文地址:https://www.cnblogs.com/liaofeifight/p/4911387.html
Copyright © 2020-2023  润新知