什么是Reactor模式
要回答这个问题,首先当然是求助Google或Wikipedia,其中Wikipedia上说:“The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated request handlers.”。从这个描述中,我们知道Reactor模式首先是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handlers;这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。如果用图来表达:
Reactor_Simple.png
从结构上,这有点类似生产者消费者模式,即有一个或多个生产者将事件放入一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事件来处理;而Reactor模式则并没有Queue来做缓冲,每当一个Event输入到Service Handler之后,该Service Handler会主动的根据不同的Event类型将其分发给对应的Request Handler来处理。
更学术的,这篇文章(Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events)上说:“The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients. Each service in an application may consistent of several methods and is represented by a separate event handler that is responsible for dispatching service-specific requests. Dispatching of event handlers is performed by an initiation dispatcher, which manages the registered event handlers. Demultiplexing of service requests is performed by a synchronous event demultiplexer. Also known as Dispatcher, Notifier”。这段描述和Wikipedia上的描述类似,有多个输入源,有多个不同的EventHandler(RequestHandler)
来处理不同的请求,Initiation Dispatcher
用于管理EventHander
,EventHandler
首先要注册到Initiation Dispatcher
中,然后Initiation Dispatcher
根据输入的Event分发给注册的EventHandler
;然而Initiation Dispatcher
并不监听Event的到来,这个工作交给Synchronous Event Demultiplexer
来处理。
Reactor模式结构
在解决了什么是Reactor模式后,我们来看看Reactor模式是由什么模块构成。图是一种比较简洁形象的表现方式,因而先上一张图来表达各个模块的名称和他们之间的关系:
Reactor_Structures.png
Handle:即操作系统中的句柄,是对资源在操作系统层面上的一种抽象,它可以是打开的文件、一个连接(Socket)、Timer等。由于Reactor模式一般使用在网络编程中,因而这里一般指Socket Handle,即一个网络连接(Connection,在Java NIO中的Channel)。这个Channel注册到Synchronous Event Demultiplexer
中,以监听Handle中发生的事件,对ServerSocketChannnel可以是CONNECT事件,对SocketChannel可以是READ、WRITE、CLOSE事件等。
Synchronous Event Demultiplexer:阻塞等待一系列的Handle中的事件到来,如果阻塞等待返回,即表示在返回的Handle中可以不阻塞的执行返回的事件类型。这个模块一般使用操作系统的select来实现。在Java NIO中用Selector来封装,当Selector.select()返回时,可以调用Selector的selectedKeys()方法获取Set<SelectionKey>,一个SelectionKey表达一个有事件发生的Channel以及该Channel上的事件类型。上图的“Synchronous Event Demultiplexer ---notifies--> Handle”的流程如果是对的,那内部实现应该是select()方法在事件到来后会先设置Handle的状态,然后返回。不了解内部实现机制,因而保留原图。
Initiation Dispatcher:用于管理Event Handler,即EventHandler的容器,用以注册、移除EventHandler等;另外,它还作为Reactor模式的入口调用Synchronous Event Demultiplexer的select方法以阻塞等待事件返回,当阻塞等待返回时,根据事件发生的Handle将其分发给对应的Event Handler处理,即回调EventHandler中的handle_event()方法。
Event Handler:定义事件处理方法:handle_event(),以供InitiationDispatcher回调使用。
Concrete Event Handler:事件EventHandler接口,实现特定事件处理逻辑。
Reactor模式模块之间的交互
简单描述一下Reactor各个模块之间的交互流程,先从序列图开始:
Reactor_Sequence.png
- 初始化
InitiationDispatcher
,并初始化一个Handle
到EventHandler
的Map
。 - 注册
EventHandler
到InitiationDispatcher
中,每个EventHandler
包含对相应Handle
的引用,从而建立Handle
到EventHandler
的映射(Map)
。 - 调用
InitiationDispatcher
的handle_events()
方法以启动Event Loop
。在Event Loop
中,调用select()
方法(Synchronous Event Demultiplexer)
阻塞等待Event发生。 - 当某个或某些
Handle
的Event
发生后,select()
方法返回,InitiationDispatcher
根据返回的Handle
找到注册的EventHandler
,并回调该EventHandler
的handle_events()
方法。 - 在
EventHandler
的handle_events()
方法中还可以向InitiationDispatcher
中注册新的Eventhandler
,比如对AcceptorEventHandler
来,当有新的client
连接时,它会产生新的EventHandler
以处理新的连接,并注册到InitiationDispatcher
中。
Reactor模式实现
在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events中,一直以Logging Server
来分析Reactor模式,这个Logging Server
的实现完全遵循这里对Reactor描述,因而放在这里以做参考。Logging Server
中的Reactor模式实现分两个部分:Client连接到Logging Server
和Client向Logging Server
写Log。因而对它的描述分成这两个步骤。
Client连接到Logging Server
-
Logging Server
注册LoggingAcceptor
到InitiationDispatcher
。 -
Logging Server
调用InitiationDispatcher的handle_events()方法启动。 -
InitiationDispatcher
内部调用select()
方法(Synchronous Event Demultiplexer
),阻塞等待Client
连接。 -
Client
连接到Logging Server
。 -
InitiationDisptcher
中的select()
方法返回,并通知LoggingAcceptor
有新的连接到来。 -
LoggingAcceptor
调用accept
方法accept
这个新连接。 -
LoggingAcceptor
创建新的LoggingHandler
。 - 新的
LoggingHandler
注册到InitiationDispatcher
中(同时也注册到Synchonous Event Demultiplexer
中),等待Client
发起写log请求。
Client向Logging Server写Log
Reactor_LoggingServer_log.png -
Client
发送log到Logging server
。 -
InitiationDispatcher
监测到相应的Handle
中有事件发生,返回阻塞等待,根据返回的Handle
找到LoggingHandler
,并回调LoggingHandler
中的handle_event()
方法。 -
LoggingHandler
中的handle_event()
方法中读取Handle
中的log信息。 - 将接收到的log写入到日志文件、数据库等设备中。
3.4步骤循环直到当前日志处理完成。 - 返回到
InitiationDispatcher
等待下一次日志写请求。
尊重原著,转载出:http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html
有关资料:http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf
网友评论