初探Tornado

Tornado是一种 Web 服务器软件的开源版本。Tornado 和主流Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。

得利于其非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。

来自百度百科的解释,其中异步非阻塞对epoll的运用是其两大特点

Tornado不同于FlaskDjango两个常见框架,主要特点是Tornado内部实现了自己的Web服务器,而Flask和Django是采用WSGI协议与服务器对接。在开发时,Flask依赖WerkzeugWSGI 工具集实现一个基于WSGI协议的内置web服务器来满足本地调试,部署的时候需要选择合适的WSGI服务器来满足生产需求。Django也是同样原理,使用内置WSGI服务器满足开发,使用其他性能更高的WSGI服务器满足生产中的并发需求。(Tornado中的web服务器和web框架都可以实现对WSGI的兼容,可以Tornado服务器模块为其他web框架提供WSGI服务器,也可以使用其他服务器来部署Tornado的web应用。)

异步非阻塞

异步和非阻塞是非常相关的而且这两个术语经常交换使用,但它们不完全相同。

为什么异步

通常情况下,web服务器对与每个客户端的请求,都会创建一个线程与其连接,这就是同步模式。在处理高并发时,对每一个请求都会创建一个线程,如此多的线程开销是服务器的压力极大。异步模式在处理了并发请求时,先将请求放到后台处理,通过事件轮询等机制,将处理好的请求发送会客户端,从而减少了线程的创建。

非阻塞

非阻塞是指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回(继续执行下面代码,或者使用重试机制)。阻塞的发生主要是由于系统IO(网络IO,文件读写IO等)引起的,或者在处理客户端请求时由于复杂的计算引起的CPU阻塞。总之阻塞的发生是由与服务器处理客户端请求需要一定的时间,直接执行(阻塞)或者直接返回,通过一定机制等到准备好要发送到客户端的内容后,发送到对应客户端。如何处理好系统IO是非阻塞的关键,Tornado是通过epoll方式的IO多路复用来实现的。

epoll

系统IO主要是程序与硬件间接交互的一种方式,如果每个程序都直接操作硬件,不仅程序开发会变得复杂,而且不同程序不统一的操作方式会使硬件混乱。因此有了操作系统,程序通过系统接口访问硬件,操作系统对所有硬件统一管理。当程序调用了系统的IO接口后,操作系统有不同的处理模式,不同的模式就是不同的IO模型。IO多路复用是一种IO模型,epoll是其中一种方式,常用的IO模型有五种:

  1. 阻塞式IO
    当调用IO请求时直接进入阻塞状态,当IO完成(包括准备数据和拷贝数据)时,进入就绪状态,等待被再次调度进入运行状态
  2. 非阻塞式IO
    当调用IO请求时,系统内核直接返回一个error信息,程序一边处理其它事情,每隔一段时间都询问内核IO数据是否准备完成,直到返回准备完成,然后把数据由内核拷贝到用户空间。
  3. IO多路复用
    多路复用把一个程序的多个IO请求整合到一起进行阻塞,主要实现方式有select,poll,epoll。
  4. 信号驱动IO
    内核通过信号通知程序IO数据已经准备好。
  5. 异步IO
    发出IO请求后,内核把数据拷贝到用户空间后,通知程序IO已经完成。

IO多路复用的方式

Tornado使用epoll(依赖依赖操作系统)的方式对网络IO进行多路复用,与客户端建立tcp连接后,能继续与其它客户端继续建立连接。接受完某客户端的数据后,调用对应的回掉函数处理。这样就能在一个线程里处理多个客户端的请求了。