• Tornado 异步以及非阻塞的I/O


    阻塞

    函数阻塞时会一直等待处理的结果才返回。阻塞情况比如网络I/O,硬盘I/O等。事实上,每一个函数都会阻塞,最少是一点点,因为他们在运行而且要使用Cpu(最有代表性的是密码hash函数bcrypt,要使用cpu的毫秒时间)。
    一个函数在一些情况下会阻塞,但是在另外一些情况下不会阻塞。如tornado.httpclient 在DNS解决方案下,当采取默认的配置时会阻塞,但是在其他网络访问的情况下不会阻塞(比如使用ThreadedResolver 或tornado.curl_httpclient)。

    异步

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

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

    异步化

    • 给RequestHandler的请求处理函数添加@tornado.gen.coroutine装饰器
    • 给RequestHandler的请求处理函数添加@tornado.web.asynchronous装饰器
    • 使用@return_future装饰器
    from tornado import gen
    
    @gen.coroutine
    def fetch_coroutine(url):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch(url)
        # 在Python 3.3之前, 在generator中是不允许有返回值的,必须通过抛出异常来代替. 如raise gen.Return(response.body).
        return response.body
    

    在Tornado 5.x版本中,这几个装饰器都被标记为deprcated(过时),我们可通过Python3.5中引入的async和await(在Python3.7中已经成为正式关键字)来达到同样的效果。当然,要实现异步化还得靠其他的支持异步操作的三方库来支持,如果请求处理函数中用到了不支持异步操作的三方库,就需要靠自己写包装类来支持异步化。

    • Postgresql: asyncpg
    • Redis: aioredis
    • I/O Framework:uvloop

    @gen.coroutine 与 @gen.engine

    tornado.gen 支持以同步方式编写异步代码的核心就是 python generator。其原理简单来说,就是通过 generator.next() 启动 yield 返回的 generator ,通过 IOLoop 与 generator.send(value) 驱动 generator 运行,以达到协调异步执行的目的。

    从功能上来看, @gen.coroutine 与 @gen.engine 的功能非常相似,差别就在于二者对被装饰方法参数中的 “callback” 参数处理不一样以及具有不同的返回值。

    • @gen.coroutine 装饰的方法执行后返回 Future 对象并且会将方法参数中的 “callback” 加入到 Future 完成后的回调列表中;
    • @gen.engine 装饰的方法执行后没有返回值(注:实际上如果被装饰方法有返回值,会抛出 ReturnValueIgnoredError 异常,详见后面的代码分析部分)。

    所以,通过 @gen.engine 装饰的方法没有返回值,方法必须自己在异步调用完成后调用 “callback” 来执行回调动作,而通过 @gen.coroutine 装饰的方法则可以直接返回执行结果,然后由 gen 模块负责将结果传递给 “callback” 来执行回调。

    @tornado.gen.coroutine + yield + raise gen.Return(d)

    • 当调用一个协程时,@tornado.gen.coroutine 与 yield 必须同时出现调用函数中
    • 如果只是在协程中执行操作或者直接返回结果,有 @tornado.gen.coroutine 和 return(raise Return)就够了
  • 相关阅读:
    青花瓷Java版
    让Broncho A1支持usbnet
    系统程序员成长计划组合的威力(三)
    【转】多CPU上的原子操作
    c#和javascript交互
    修改代码时有时会出现找不到某个组件
    UML用例建模的慨念和应用
    DJ曲二
    查询数据库里的存储过程的文本中的某个内容
    UML静态建模
  • 原文地址:https://www.cnblogs.com/bsszds930/p/12957185.html
Copyright © 2020-2023  润新知