7.4 Reactor 模式
目前存在很多的网络通信库,从 C/C++ 的 libevent 库,到 Java 的 Netty 框架,再到 python 的 Twisted 库等,目前主流的网络库使用的都是 Reactor 模式(中文译作: 反应器模式或反射器模式)。那么到底什么是 Reactor 模式呢?Reactor 模式有什么优点?Reactor 模式英文解释如下:
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.
翻译成中文的意思就是:
反应器设计模式( Reactor pattern )是一种事件处理设计模式,该模式可以将一个或多个 IO 请求服务并发地传递给服务处理器,即当( IO 处理)请求抵达后,服务处理程序使用多路复用技术,然后同步地派发这些请求至相关的请求处理程序。
流程图如下:
从流程图上来看,这个设计模式看起来很简单,其背后却蕴含着不简单的设计思想。那么上图中到底蕴含着什么样的思想奥妙呢?它解决了计算机世界中普遍存在的一个问题,即请求太多,资源太少。也就是说一个对外服务程序,其接收的各种输入输出请求的数量可能是非常多的,然后由于处理能力有限,其处理这些请求的资源数量是有限的。诚然,大千世界也是这样,如一个公园的游客容量是有限的,而游客数量可能是无限的;一个饭店的座位是有限的,而顾客可能是无限的;一个国家的领土是有限的,其人口可能是无限增长的。所以上图中输入输出请求数量之和一般会远远大于处理程序数量,而多路复用器(IO Demultiplexer)将这些数量众多的输入输出请求分发给有限的处理程序。
所以一个 Reactor 模式结构一般包含以下模块:
资源请求事件(Resource Request)
多路复用器与事件分发器(IO Demultiplexer & Event Dispatcher)
事件处理器(EventHandler)
我们以目前大多数饭店的运营模式这样一个生活中的例子来说明一下reactor模式,顾客去饭店吃饭,由于客户较多,饭店的服务员数量有限,所以饭店都是某个服务员负责某几桌客户,当顾客有需求时(点菜、结账等),可以把需要告诉服务员,由服务员去把这些需求再转发给其他相关人员(点菜转发给厨房,结账交给收银)。如此操作,在即使饭店顾客爆满时,靠几个服务员也能有条不紊地运转着整个饭店。
这是很简单的生活例子,却有着最朴素的思想,在对应具体的服务器程序技术上来说,以 socket 的读写为例,输入输出请求就是 socket 上有数据可读或者需要往 socket 上写入数据,而 IO 复用器就对应着操作系统的相关 API,Windows 操作系统上有 select 技术(函数),Linux 上有 select 函数、poll 函数、epoll 模型(实际对应 epoll_wait)。使用这些IO复用技术之后,Reactor 模式对应的流程图就变成了如下结构: