华盛顿大学的论文 Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events 讲了Reactor模式的设计。大体看了一下,发现也不是很复杂,而且也没有想象中的有新意。(可能这篇论文比较久了,有更新的Reactor模式等,这里只是大体了解其意)。
Reactor,反应堆设计模式,读论文《Reactor, An Object Behavioral Pattern for Demultiplexingand Dispatching Handles for Synchronous Events》笔记。
1) Intent
Reactor设计模式用来处理(由一个或多个客户端发出的)并发(concurrently)的服务请求。
initiation dispather,synchronous event demultiplexer.
3) Example
多线程服务器的缺点:效率低(由于上下文切换,同步等),编程复杂性(编程较复杂),可移植性差。
5) Problem
注意单词demultiplex,意思是多路分用,跟multiplex,多路复用正好是反义词。
服务器应用在触发某一个服务之前,需要demultiplex并且将客户端的请求分发到对应的服务提供者,Reactor就是做这个工作的吧。
6) Solution
a.将demultiplex跟分发(dispatching)事件的处理程序整合在一起;b. 将特定事件的分发与服务的实现 与通用的多路分用和分发机制解耦合。
Event Handler:特定类型事件的处理程序,Event Handler注册到Initiation Dispatcher中,后者使用 Synchronous EventDemultiplexer来等待特定事件的发生。当某个事件发生的时候,Synchronous Event Demultiplexer(同步事件多路分用器?)通知Initiation Dispatcher,后者同步调用Event Handler,后者最终处理事件。
上面这一段介绍了一个名词,有三个:Event Handler、Initiation Dispatcher、Synchronous Event Demultiplexer。
7) Structure
这一部分介绍了Reactor模式中的主要组成元素,在第6)部分已经介绍了几个了,这一部分介绍的更详细一些。
Handles:这里可以认为是Unix中的的文件描述符(fd),用来标识一个客户端连接,Synchronous Event Demultiplexer(同步事件多路分用器)在这些handles上等待事件的发送。
SynchronousEvent Demultiplexer:这个可以称为“同步事件多路分用器”的东西阻塞在一些handle上,等待事件的发生,一个常见的“同步事件多路分用器”是select(好熟悉的东西啊,就是UNIX和Win32 OS中的select)。
InitiationDispather:翻译为“初始分发器”? 为Event Handler定义了一组操作接口,包含注册(registering),移除(removing),分发(dispatching) Event Handler。最终地,由Synchronous Event Demultiplexer来等待事件发生,当事件发生时,select通知Initiation Dispather来调用应用特定的事件处理器(Event handler)。通常事件包括:accept,read,write,timeout等。
EventHandler:事件处理器的接口类型,向Initiation Dispather中注册的都是接口。
ConcreteEvent Handler:具体的事件处理器,继承自Event Handler,可以理解为不同的具体事件处理器对不同的事件感兴趣(在下面用reactor反应堆实现的epoll编程中,直接对具体的时间处理器,即一个函数指针,回调函数,作为一个fd的额外的用户数据,保存在epoll_event的data域中)。
以上五种元素的关系大体如下:
文章以一个日志服务器(Logging Server)描述了两个reactor的工作场景,下面以一个客户端连接到服务器为例说明,工作过程如下图:
a)、日志服务器(1)将具体事件处理器Logging Acceptor(这个处理器用来接收client请求,并为添加一个client是否可以read的事件)注册到Initiation Dispatcher。
b)、日志服务器调用Initiation Dispatcher的handle_events函数来进行事件循环(2),在普通的epoll编程中,这个就是包括了epoll_wait的while循环。
c)、Initiation Dispatcher调用Synchronous Event Demultiplexer(比如select,这里用的就是select)来进行阻塞等待(3)。
d)、一个client 请求connect。(4)
e)、Initiation Dispatcher通知Logging Acceptor来处理事件(你活来了,快来干活),(5)。
f)、Logging Acceptor接受(accept)了一个新的请求。(6)
g)、Logging Acceptor并且创建了一个具体时间处理器Logging Handler,这个Logging Handler用来读取这个client连接的日志数据。
h)、Logging Handler注册自己到Initiation Dispatcher中,并等待他的通知。