• 摘要:异步和非阻塞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. 数据结构----线性表顺序和链式结构的使用(c)

    PS:在学习数据结构之前,我相信很多博友也都学习过一些语言,比如说java,c语言,c++,web等,我们之前用的一些方法大都是封装好的,就java而言,里面使用了大量的封装好的方法,一些算法也大都写 ...

  2. 数组sort()方法排序

    sort()方法排序 var arr = ["G","A","C","B","I","H& ...

  3. bootstrap 默认显示1899问题

    今天使用bootstrap的 dateTimePicker控件时候,又碰到了去年的 显示 1899年的问题,之前解决过,但是忘记了.就记得 他的代码里面有一段是 说格式不正确或者 时间格式小于某个值时 ...

  4. 【Leetcode】【Easy】Path Sum

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  5. 微软操作系统 Windows Server 2012 R2 官方原版镜像

    微软操作系统 Windows Server 2012 R2 官方原版镜像 Windows Server 2012 R2 是由微软公司(Microsoft)设计开发的新一代的服务器专属操作系统,其核心版 ...

  6. FQDN说明

    以下摘自百度百科: FQDN:(Fully Qualified Domain Name)完全合格域名/全称域名,是指主机名加上全路径,全路径中列出了序列中所有域成员.全域名可以从逻辑上准确地表示出主机 ...

  7. 【系统】在windows中追加/删除虚拟打印机

    由于项目需要在windwos系统中添加多台虚拟打印机(能够正常打印出纸),查找了一下系统函数. 使用 rundll32 printui.dll,PrintUIEntry,在CMD中运行,在弹出框中得到 ...

  8. TIAGO机器人传感器参数简介 手册翻译

    本来认为这篇文章是最没人气的,竟然收到了回复,看来要继续更新本文了.留下笔者联系方式,邮箱leop22@163.com,欢迎邮件交流. 防止不良爬虫,原文链接:http://www.cnblogs.c ...

  9. EventBus事件总线

    EventBus事件总线的使用-自己实现事件总线   在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务 ...

  10. 记一种c++字符串格式化方法

    std::string str_fmt(const char * _Format, ...) { std::string _str; va_list marker = NULL; va_start(m ...