Reactor

【Reactor】

Reactor设计模式在高性能I/O框架中随处可见,例如redis,tornado,gevent,libevent等。

Reactor可以翻译为反应器,是一种基于事件驱动的设计模式。那么它是如何运作的呢?其实很多设计模式都来源于生活中的一些常见的处理事情的方式。

我们先来看一个例子:你和妹子去购物中心吃饭,发现很多人在排队,这时只需要让前台在电脑上填上你需要的双人位,和你的手机号码,待会有位置的时候会发短信给你,这时候你可以陪妹子到处逛逛,买买买。当餐厅有双人位空出的时候,就会发短信或打电话给你,这时你就可以带妹子去吃饭了。

上面例子中,你没有呆呆的排队等餐厅有位,你还陪妹子去逛街买了很多东西,整个过程都是不阻塞的,效率非常之高。这里面餐厅充当了Reactor的作用,他帮你一直盯着,等有位置空出的时候,就做出相应的反应:根据你所填的手机号码,通知你可以就餐。

总结:在Reactor模式中,处理事件的程序不会去调用反应器,而是告诉Reactor监听一个事件,和这个事件发生时处理方法,当Reactor监测到这个事件发生时,就启动对应的处理方法(一般是回调函数)进行处理,这种控制逆转又称为“好莱坞法则”(不要调用我,让我来调用你)。

【Reactor设计模式】

在Reactor模式中,有5个关键的参与者。[引用]

1. 描述符(handle):由操作系统提供,用于识别每一个事件,如Socket描述符、文件描述符(fd)等。在Linux中,它用一个整数来表示。事件可以来自外部,如来自客户端的连接请求、数据等。事件也可以来自内部,如定时器事件。
2. 同步事件分离器(demultiplexer):是一个函数,用来等待一个或多个事件的发生。调用者会被阻塞,直到分离器分离的描述符集上有事件发生。Linux的select函数是一个经常被使用的分离器。
3. 事件处理器接口(event handler):是由一个或多个模板函数组成的接口。这些模板函数描述了和应用程序相关的对某个事件的操作。
4. 具体的事件处理器(concrete event handler):是事件处理器接口的实现。它实现了应用程序提供的某个服务。每个具体的事件处理器总和一个描述符相关。它使用描述符来识别事件、识别应用程序提供的服务。
5. Reactor 管理器(reactor):定义了一些接口,用于应用程序控制事件调度,以及应用程序注册、删除事件处理器和相关的描述符。它是事件处理器的调度核心。 Reactor管理器使用同步事件分离器来等待事件的发生。一旦事件发生,Reactor管理器先是分离每个事件,然后调度事件处理器,最后调用相关的模 板函数来处理这个事件。

下面是Reactor结构图

此处输入图片的描述

可能从上面来看比较难理解,那么我们从最开始的例子来分析这几个角色的作用。
你告诉前台MM (Reactor:负责后面的所有操作的调度)你需要一个双人位(handle:就是一个等待双人位的事件),并告知手机号码(concrete event handler:当有双人位时,通过这个手机联系你,是具体的事件的处理方法),而她会往她的电脑中添加一条记录(event handler:记录着双人位和你的联系方式,将事件和处理方式绑定到一起),当某一桌双人位结账时,电脑从一堆排号信息中自动检测到有空余双人位(demultiplexer:将空余双人位事件从其他还在等待发生的事件中分离出来),前台MM根据电脑记录找到你的电话号码,然后通过电话通知你可以前来就餐。
希望到这里你已经把Reactor的各个角色的作用弄清楚了,下次就可以去读一些使用Reactor设计模式的源码了,这里推荐 libevent

【Reactor的特点】

最后总结一下Reactor的优点:
1. 响应快:不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的。
2. 编程相对简单: 可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销。
3. 可扩展性: 可以方便的通过增加Reactor实例个数来充分利用CPU资源。
4. 可复用性: reactor框架本身与具体事件处理逻辑无关,具有很高的复用性。

文章目录
  1. 1. 【Reactor】
  2. 2. 【Reactor设计模式】
  3. 3. 【Reactor的特点】
,