http://www.tornadoweb.org/en/stable/guide/async.html

Real-time web features require a long-lived mostly-idle connection per user. In a traditional synchronous web server, this implies
devoting one thread to each user, which can be very expensive.
在同步状态下,实时的网络请求会一直占用着一个空的连接,这样每一个用户都会占用着一个线程,很浪费

To minimize the cost of concurrent connections, Tornado uses a single-threaded event loop. This means that all application code should aim to be asynchronous and non-blocking because only one operation can be active at a time.
为了最大限度的利用连接,Tornado使用单线程事件循环的方式。就是使应用采用异步和非阻塞的方式保持着当下只有一个活动的事件,同时又能接收多个应用请求。

The terms asynchronous and non-blocking are closely related and are often used interchangeably, but they are not quite the same thing.
异步和非阻塞这两个术语通常意思一样,但是他们也有不同的地方。

Blocking

A function blocks when it waits for something to happen before returning. A function may block for many reasons: network I/O, disk I/O, mutexes, etc. In fact, every function blocks, at least a little bit, while it is running and using the CPU (for an extreme example that demonstrates why CPU blocking must be taken as seriously as other kinds of blocking, consider password hashing functions like bcrypt, which by design use hundreds of milliseconds of CPU time, far more than a typical network or disk access).
等待这个功能模块返回结果前,函数有很多阻塞的原因,比如:网络I/O、磁盘I/O、互斥操作等。事实上每个功能模块在它运行的时候都会使用一点CPU资源(CPU阻塞必须要当做其它类型的阻塞)

A function can be blocking in some respects and non-blocking in others. For example, tornado.httpclient in the default configuration blocks on DNS resolution but not on other network access (to mitigate this use ThreadedResolver or a tornado.curl_httpclient with a properly-configured build of libcurl). In the context of Tornado we generally talk about blocking in the context of network I/O, although all kinds of blocking are to be minimized.
函数能在一些方面阻塞,在另一些方面不阻塞,**,在Tornado下我们一般讨论的是网络I/O阻塞,其它情况都是很小的。 Tornado里面讨论的阻塞都是指网络阻塞,其它的阻塞可以忽略。*

Asynchronous

An asynchronous function returns before it is finished, and generally causes some work to happen in the background before triggering some future action in the application (as opposed to normal synchronous functions, which do everything they are going to do before returning). There are many styles of asynchronous interfaces:
异步函数会在执行结束之前返回,在完成之后通常是一些后台程序去触发预先设定好的处理程序(不像同步程序,必须都做完了才返回)。下面列举了很多种风格的异步接口。

  • Callback argument 回调参数
  • Return a placeholder (Future, Promise, Deferred) 返回一个占位符
  • Deliver to a queue 交付到队列中
  • Callback registry (e.g. POSIX signals) 回调到注册表中

Regardless of which type of interface is used, asynchronous functions by definition interact differently with their callers; there is no free way to make a synchronous function asynchronous in a way that is transparent to its callers (systems like gevent use lightweight threads to offer performance comparable to asynchronous systems, but they do not actually make things asynchronous).
无论使用哪种接口,异步函数都会使用不同的方式与调用者交互;没有办法去定义一个同步函数却采用异步的方式调用,对于调用者来说都是透明的(就像采用gevent的轻量级线程系统去提供做到的性能堪比异步系统,但它实际上并不是异步)。
这句话的意思就是说同步的方法没法用异步的方式去调,虽然你写的代码看起来像是异步的,但其实并不是。

Examples

Here is a sample synchronous function:
下面的例子是一个同步函数。

1
2
3
4
5
6
from tornado.httpclient import HTTPClient
 
def synchronous_fetch(url):
http_client = HTTPClient()
response = http_client.fetch(url)
return response.body

And here is the same function rewritten to be asynchronous with a callback argument:
下面的例子被重写成异步的方式了,采用了回调参数的方式。

1
2
3
4
5
6
7
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)

And again with a Future instead of a callback:
下面的例子通过返回一个展位符的方式实现异步回调的。

1
2
3
4
5
6
7
8
9
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

The raw Future version is more complex, but Futures are nonetheless recommended practice in Tornado because they have two major advantages. Error handling is more consistent since the Future.result method can simply raise an exception (as opposed to the ad-hoc error handling common in callback-oriented interfaces), and Futures lend themselves well to use with coroutines. Coroutines will be discussed in depth in the next section of this guide. Here is the coroutine version of our sample function, which is very similar to the original synchronous version:
通过Future的方式实现的更复杂,但是Tornado更建议这样去写,主要有两个原因。从Future返回的错误处理更一致,从Future.result方法可以返回一个简单的异常,Future能够更好的与协同程序一起使用。协同程序的具体讨论将会在下一节讨论,下面的例子给了一个协同程序的例子,写法很像同步的那个版本。

1
2
3
4
5
6
7
from tornado import gen
 
@gen.coroutine
def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(url)
raise gen.Return(response.body)

The statement raise gen.Return(response.body) is an artifact of Python 2, in which generators aren’t allowed to return values. To overcome this, Tornado coroutines raise a special kind of exception called a Return. The coroutine catches this exception and treats it like a returned value. In Python 3.3 and later, a return response.body achieves the same result.
这个版本中返回一个raise gen.Return(response.body),在Python2中的用法,因为生成器不允许返回一个值,所以Tornado做了特殊处理,通过跑出一个Return的异常,然后协同程序补货这个异常,就相当于返回值了。在Python3.3以后就可以直接返回这个值了。

Translated by zhangxu on 2016-08-05

Asynchronous and non-Blocking I/O 翻译[收藏好文]的更多相关文章

  1. 中文翻译:pjsip文档(四)之ICE Session的使用方法

    1:pjsip教程(一)之PJNATH简介 2:pjsip教程(二)之ICE穿越打洞:Interactive Connectivity Establishment简介 3:pjsip教程(三)之ICE ...

  2. YUV视频格式详解(翻译自微软文档)

    原文: https://docs.microsoft.com/en-us/previous-versions/aa904813(v=vs.80) YUV视频格式详解(翻译自微软文档)https://b ...

  3. [翻译] Autofac 入门文档

    原文链接:http://docs.autofac.org/en/latest/getting-started/index.html 在程序中使用Autofac的基本模式是: 用控制反转(IoC)的思想 ...

  4. HugePages概述--翻译自19C文档

    翻译自: https://docs.oracle.com/en/database/oracle/oracle-database/19/unxar/administering-oracle-databa ...

  5. 使用 Python 翻译 CHM 帮助文档

    此方法绝对切实可行 翻译成品项目: https://github.com/foyoux/InstallShield2020-Documents 效果预览 安装 docts 库 pip install ...

  6. React翻译官网文档之JSX

    什么是JSX? 看下面的代码它被称为JSX,它既不是字符串也不是HTML,而是一种facebook公司对javascript语法的拓展.虽然写法很奇怪最终仍会会被编译为javascript代码 con ...

  7. 翻译:SockJS-node文档(一)

    什么是SockJS? SockJS是一个提供Websocket通信的JavaScript库,目的是实现在浏览器与服务器之间低延迟.全双工.跨域通信,它提供跨浏览器的统一API,即使不支持HTML5 W ...

  8. Why should I avoid blocking the Event Loop and the Worker Pool?

    Don't Block the Event Loop (or the Worker Pool) | Node.js https://nodejs.org/en/docs/guides/dont-blo ...

  9. 基于百度翻译API开发属于自己的翻译工具

    你是否每天使用着网页翻译工具?你是否遇到过这种情况,上网过程中遇到一个很长的单词但是又不能复制,要开两个浏览器,一个打开百度翻译,照着另一个网页输入单词?你安装了各种翻译软件后,又删除,只因忍受不了那 ...

随机推荐

  1. Java 读取 .properties 配置文件

    java 开发中,经常要读取 properties 配置文件,下面介绍几种读取方式: 1.基于 InputStream 读取配置文件 该方式的优点在于可以读取任意路径下的配置文件 Properties ...

  2. PHP 7中利用OpenSSL代替Mcrypt加解密的方法详解

    php7.1发布后新特性吸引了不少PHPer,大家都在讨论新特性带来的好处与便利.但是从php7.0 升级到 php7.1 废弃(过时)了一个在过去普遍应用的扩展(mcrypt扩展).官方提供了相应的 ...

  3. Android -- Interpolator

    Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等. ...

  4. Redis实战总结-Redis的高可用性

    在之前的博客<Redis实战总结-配置.持久化.复制>给出了一种Redis主从复制机制,简单地实现了Redis高可用.然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的 ...

  5. 浮动闭合最佳方案:clearfix

    之前给大家介绍两种浮动闭合的办法CSS清除浮动 万能float闭合,得知很多同学都在使用下面的骨灰级解决办法: .clear{clear:both;height:0;overflow:hidden;} ...

  6. 小教程:自己创建一个jQuery长阴影插件

    长阴影设计是平面设计的一个变体,添加了阴影,产生了深度的幻觉,并导致了三维的设计.在本教程中,我们将创建一个jQuery插件,通过添加完全可自定义的长阴影图标,我们可以轻松地转换平面图标. 戳我查看效 ...

  7. ScrollView嵌套ListView只显示一行解决方案

    在ScrollView里边嵌套了个ListView,后边就发现数据源里好多数据,但ListView只是显示1行. 各种debug,打log,数据什么的都没问题,上网百度了下,发现原来是ScrollVi ...

  8. C++缓冲区溢出

    测试代码: #include <stdlib.h> #include <string.h> #include <stdio.h> int main() { ] =& ...

  9. ZH奶酪:Python中zip函数的使用方法

    定义:zip([iterable, …]) zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些 tuples组成 ...

  10. LevelDB初体验测试

    最近工作需要找一个能使用磁盘存储数据,对写要求比较苛刻,需要每秒达100000TPS,读的时候需要能10000TPS左右,不能占用太多内存.单节点满足这个要求的常见有Redis.Memcached等, ...