Reactor模式
Reator的事件处理机制
Reactor翻译为“反应堆”,是一种事件驱动机制。该机制和普通函数调用的不同在于:应用程序不是主动调用某个API完成处理,相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,吐过相应的事件发生,Reactor将主动调用应用程序注册的接口,这些接口又被称为“回调函数(callback)”。
使用libevent也是向libevent框架注册相应的事件和回调函数,当这些事件发生时,libevent会调用这些回调函数来处理相应的事件(I/O、定时、信号)。
Reactor模式的优点
- 响应快,不必为单个同步事件所阻塞,虽然Reactor本身是同步
- 编程简单,可以最大程度地避免复杂地多线程和同步问题,并且避免了多线程/进程地切换开销
- 可扩展性,可以方便地通过增加Reactor实例个数来充分利用CPU资源
- 可复用性:Reactor框架本身与具体事件处理逻辑无关,具有较高地复用性
Reacotr模式框架
使用Reactor模型,必备地几个组件:事件源、Reactor框架、多路复用机制和事件处理程序。
-
事件源
Linux上是文件描述符,Windows上就是socket或者handle,这里统一称为“句柄集”;程序在指定句柄上注册关心地事件,比如I/O事件。 -
event demultiplexer——事件多路分发机制
由操作系统提供地I/O多路复用机制,比如select和epoll。程序首先将其关心地句柄(事件源)及其事件注册到event demultiplexer上;当有事件到达时,event demultiplexer会发出通知“在已注册地句柄集中,一个或多个句柄地事件已经就绪”;程序收到通知后,就可以在非阻塞地情况下对事件进行处理了。
对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外屏蔽底层系统的目的。
- Reactor——反应器
Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件,并运行事件循环;当事件进入“就绪“状态时。调用注册事件的回调函数处理事件。
对应到libevent中,就是event_base结构体。
一个典型的Reactor声明方式:
class Reactor
{
public:
int registerHandler(EventHandler *pHandler, int event);
int removeHandle(EventHandler *pHandler, int event);
void handleEvents(timeval *ptv);
// ...
}
- Event Handler——事件处理程序
事件处理程序提供一组接口,每个接口对应一类事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。通常它会绑定一个有效的句柄。
对应到libevent中,就是event结构体。
下面是两种典型的Event Handler类声明方式:
class EventHandler
{
public:
virtual void handleRead() = 0;
virtual void handleWrite() = 0;
virtual void handleTimeout() = 0;
virtual void handleClose() = 0;
virtual HANDLE getHandle() = 0;
// ...
}
;
class EventHandler
{
public:
// events maybe read/write/timeout/close .etc
virtual void handleEvents(int events) = 0;
virtual HANDLE getHandle() = 0;
// ...
}