• 摘要:异步和非阻塞I/O实时WEB的特性是经常需要为每个用户端维持一个长时间存活但是大部分时候空闲的连接。在传统的同步式web服务器中,这主要通过为每个用户创建一个线程来实现,这样的代价是十分昂贵的。为了最大限度地减少并发成本,Tornado使用单线程的事件循环机制(linux中是基于epoll的).这就意味着所有的应用代码都应该是异步或非阻塞的,因为同时只能有一个操作是活动的。尽管异步和非阻塞这2个术语是密切相关的,并且通常可以互换使用,但并不完全相同。阻塞当一个函数在等待某些事
    • 异步和非阻塞I/O

      实时WEB的特性是经常需要为每个用户端维持一个长时间存活但是大部分时候空闲的连接。在传统的同步式web服务器中,这主要通过为每个用户创建一个线程来实现,这样的代价是十分昂贵的。

      为了最大限度地减少并发成本,Tornado使用单线程的事件循环机制(linux中是基于epoll的).这就意味着所有的应用代码都应该是异步或非阻塞的,因为同时只能有一个操作是活动的。

      尽管异步和非阻塞这2个术语是密切相关的,并且通常可以互换使用,但并不完全相同。

      阻塞
      当一个函数在等待某些事件的时候就会阻塞。一个函数阻塞的原因有很多:网络I/O,磁盘I/O,锁等等。
      实际上,所有的函数在使用CPU的时候,都多多少少的会阻塞,至少会有一点点。
      下面有一个极端的例子演示了为什么CPU阻塞比其他类型的阻塞还要严重。
      密码哈希函数比如bcrypt,被设计为要使用数百ms的CPU时间,远远大于通常的网络或磁盘访问。

      一个函数可以在某些方面阻塞,也可以在某些方面非阻塞。
      比如,在默认配置下,tornado.httpclient会在DNS解析时阻塞但是不会在其他网络访问时阻塞(为了缓解这种状况,可以使用ThreadResolver和tornado.curl_httpclient
      它们是通过合适的配置用libcurl来构建的)
      在tornado的背景中,我们一般只讨论网络I/O下的阻塞,尽管其它类型的阻塞也被最小化了。

      异步
      一个异步函数在它完成之前返回,在应用程序触发一些未来的动作之前,需要在后台做一些工作。这与同步函数正好相反,同步函数在返回之前把所有要做的事件都做完。
      有许多类型的异步接口:
      1.回调函数参数
      2.返回一个占位符(Future,Promise,Deferred)
      3.发送到队列
      4.回调函数注册(比如POSIX标准的信号)
      不管何种类型的异步接口,调用者都采用不同方式使用这些异步接口。把同步函数转换为异步函数需要采用一定的方法,这种转换对调用者是透明的。(一些系统比如gevent使用
      轻量级的线程来提供与异步系统相似的性能,但是它们并不是真正地异步)

      举例
      下面是一个同步函数的例子:
      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)

      还可以用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无条件地建议在实际编程中使用Future,因为有以下2点好处:
      1.使错误处理更加一致,因为Future.result方法可以简单地抛出一个异常
      2.Future很好地使用了coroutines.Coroutines将在下一节进行更深的讨论。
      下面是一个coroutine版本的异步函数,与最开始的同步函数十分相似:
      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)语句是一个包装在python2和python3.2里,因为python的这些版本不支持将生成器函数作为返回值。
      为了克服这个,Tornado coroutines抛出一个特殊种类的异常,称为Return. 
      coroutine捕获这个异常并将它当作一个返回值。
      在Python3.3和之后的版本里面,使用"return response.body"的效果是一样的。

Tornado用户指引(一)-----------异步和非阻塞I/O的更多相关文章

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

    Read-time(实时)的网站需要针对每个用户保持长时间的连接.在传统的同步网站服务中,通常针对每个用户开启来一个线程来实现,但是这样做非常昂贵. 为了使并发连接的成本最小化,Tornada使用单个 ...

  2. 关于并发,异步,非阻塞(python)疑惑的一些资料解答

    从iterable/iterator到generator到coroutine理解python的迭代器: http://python.jobbole.com/81916/理解python的生成器: ht ...

  3. 通俗讲解 异步,非阻塞和 IO 复用

    1. 阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 1.1 同步与异步 同步与异步的理解 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步: 当一个同 ...

  4. 转:IO模型-- 同步和阻塞,异步和非阻塞的区别

    源地址 http://hi.baidu.com/deep_pro/item/db0c581af1c1f17e7b5f2534 这些词之间的区别难倒了很多人,还有什么同步阻塞, 同步非阻塞, 异步阻塞, ...

  5. tornado异步请求非阻塞

    前言也许有同学很迷惑:tornado不是标榜异步非阻塞解决10K问题的嘛?但是我却发现不是torando不好,而是你用错了 比如最近发现一个事情:某网 前言 也许有同学很迷惑:tornado不是标榜异 ...

  6. tornado异步请求非阻塞-乾颐堂

    前言 也许有同学很迷惑:tornado不是标榜异步非阻塞解决10K问题的嘛?但是我却发现不是torando不好,而是你用错了.比如最近发现一个事情:某网站打开页面很慢,服务器cpu/内存都正常.网络状 ...

  7. tornado : 异步、非阻塞

    The terms asynchronous and non-blocking are closely related and are often used interchangeably, but ...

  8. 异步、非阻塞和IO多路复用总结

    Nginx是并发处理框架的代表者,很多后台业务都会放在Nginx容器中运行,以实现高吞吐,而Nginx能够支持高并发也是由于使用了异步非阻塞处理模型,本文将用通俗的话讲解异步.同步.阻塞.非阻塞的区别 ...

  9. tornado用户指引(二)------------tornado协程实现原理和使用(一)

    摘要:Tornado建议使用协程来实现异步调用.协程使用python的yield关键字来继续或者暂停执行,而不用编写大量的callback函数来实现.(在linux基于epoll的异步调用中,我们需要 ...

随机推荐

  1. Python爬虫教程-29-验证码识别-Tesseract-OCR

    本篇是关于验证码识别问题,也是Python爬虫笔记的一个结尾,使用 Tesseract Python爬虫教程-29-验证码识别-Tesseract-OCR 常见反爬虫手段: 验证码 1.简单图片,扭曲 ...

  2. 4 关于word2vec的skip-gram模型使用负例采样nce_loss损失函数的源码剖析

    tf.nn.nce_loss是word2vec的skip-gram模型的负例采样方式的函数,下面分析其源代码. 1 上下文代码 loss = tf.reduce_mean( tf.nn.nce_los ...

  3. c# 依赖注入之---setterInjection(转)

    图3.1 Setter注入示意 定义一个接口: namespace SetterInjection { internal interface IServiceClass { string Servic ...

  4. centos 克隆系统放到别的机器上后出现网卡启动不了的情况

      1. Remove Network Manager from startup Services. #chkconfig NetworkManager off 2. Add Default Net ...

  5. 使用 Azure CLI 将 IaaS 资源从经典部署模型迁移到 Azure Resource Manager 部署模型

    以下步骤演示如何使用 Azure 命令行接口 (CLI) 命令将基础结构即服务 (IaaS) 资源从经典部署模型迁移到 Azure Resource Manager 部署模型. 本文中的操作需要 Az ...

  6. PPTP vs. OpenVPN vs. L2TP/IPsec vs. SSTP

    Which is the Best VPN Protocol? PPTP vs. OpenVPN vs. L2TP/IPsec vs. SSTP Want to use a VPN? If you’r ...

  7. 错误: 安装必备组件失败: 安装必备组件失败: SqlInstanceRtc 有关详细信息

    错误: 安装必备组件失败: 安装必备组件失败: SqlInstanceRtc 有关详细信息 查看错误得知是安装sqlexpr_x64.exe的时候出现了错误 解决: 通过打开skype镜像,找到sql ...

  8. msvcr100.dll问题描述及修复方式

    出现问题的大部分原因是因该文件被木马病毒破坏导致系统找不到此文件,出现错误提示框,想要解决此问题只需找到专业的DLL文件下载网站,下载该文件,复制到相应目录.即可解决.msvcr100.dll为Vis ...

  9. 沉淀,再出发:Git的再次思考

    沉淀,再出发:Git的再次思考 一.前言 使用git也有很久了,后来有一段时间一直没有机会去使用,现在想来总结一下自己学习了这么长时间的一些心得感悟,我写的博客一般都是开了一个轮廓和框架,等到以后有所 ...

  10. 设计模式:桥接(Bridge)模式

    设计模式:桥接(Bridge)模式 一.前言   写到这里,基本上就是对前面几种模式的扩展和区别了,可以看到我们前面的几种模式,很多时候都出现了重叠,这里要分清一个概念,模式并不是完全隔离和独立的,有 ...