libevent源码分析(二) Reactor模式

由于 l i b e v e n t libevent libevent本身就是一个 R e a c t o r Reactor Reactor,所以了解 R e a c t o r Reactor Reactor这样一个应用于服务端的开发设计模式很有必要。

1. R e a c t o r Reactor Reactor模式

借由 W i k i p e d i a 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."

从这个描述中我们能了解到 R e a c t o r Reactor Reactor模式是事件驱动的,有一个或多个并发输入源,有一个 S e r v i c e Service Service H a n d l e r Handler Handler,有多个 R e q u e s t Request Request H a n d l e r Handler Handler;这个 S e r v i c e Service Service H a n d l e r Handler Handler会同步的将输入的请求( E v e n t Event Event)多路复用的分发给相应的 R e q u e s t Request Request H a n d l e r Handler Handler

2. R e a c t o r Reactor Reactor模式的事件处理机制

不同于普通的函数调用,应用程序不是主动的调用某个 A P I API API完成处理,恰恰相反; R e a c t o r Reactor Reactor 逆置了事件处理流程,应用程序需要提供相应的接口并注册到 R e a c t o r Reactor Reactor 上,如果相应的事件发生, R e a c t o r Reactor Reactor 将主动调用应用程序注册的接口,这些接口又称为 C a l l b a c k Callback Callback函数(回调函数)。使用 l i b e v e n t libevent libevent 也是想 l i b e v e n t libevent libevent 框架注册相应的事件和回调函数;当这些事件发生时, l i b e v e n t libevent libevent 会调用这些回调函数处理相应的事件( I / O I/O I/O 读写、定时和信号)。

3. R e a c t o r Reactor Reactor模式具备的优点
R e a c t o r Reactor Reactor 模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:

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

4. R e a c t o r Reactor Reactor模式框架

使用 R e a c t o r Reactor Reactor模型必备的几个组件:事件源、 R e a c t o r Reactor Reactor框架、多路复用机制以及事件处理机制,如下图:

libevent源码分析(二) Reactor模式_第1张图片
(一)事件源
L i n u x Linux Linux 上是文件描述符, W i n d o w s Windows Windows 上就是 S o c k e t Socket Socket 或者 H a n d l e Handle Handle 了,这里统一称为“句柄 集”;程序在指定的句柄上注册关心的事件,比如 I / O I/O I/O 事件。

(二) e v e n t event event d e m u l t i p l e x e r demultiplexer demultiplexer——事件多路分发机制
由操作系统提供的 I / 0 I/0 I/0多路复用机制,比如 s e l e c t select select p o l l 以 及 e p o l l poll以及epoll pollepoll

  • 1.首先,程序将其关心的 e v e n t event event注册到 e v e n t event event d e m u l t i p l e x e r demultiplexer demultiplexer
  • 2.当有事件到达时, e v e n t event event d e m u l t i p l e x e r demultiplexer demultiplexer会发出一个通知,告诉 H a n d l e Handle Handle在已注册的 e v e n t event event中,有一个或多个 e v e n t event event准备就绪;
  • 3.程序收到通知后,以非阻塞的方式对事件进行处理

对应到 l i b e v e n t libevent libevent 中,依然是 s e l e c t select select p o l l poll poll e p o l l epoll epoll 等,但是 l i b e v e n t libevent libevent 使用结构体 e v e n t o p eventop eventop 进行了封装,以统一的接口来支持这些 I / O I/O I/O 多路复用机制,达到了对外隐藏底层系统机制的目的。

(三) R e a c t o r Reactor Reactor–反应器
R e a c t o r Reactor Reactor,事件处理的接口。内部使用 e v e n t event event d e m u l t i p l e x e r demultiplexer demultiplexer进行注册、注销事件;并运行事件循环;当有事件准备就绪,调用注册事件的回调函数处理事件。

对应到 l i b e v e n t libevent libevent,就是 e v e n t event event_ b a s e base base结构体。

常用的 R e a c t o r Reactor Reactor声明:

class Reactor {
public:
	int register_handler(Event_Handler *pHandler, int event); 
	int remove_handler(Event_Handler *pHandler, int event); 
	void handle_events(timeval *ptv); 
	// ... 
};

(四) E v e n t Event Event H a n d l e Handle Handle—事件处理程序
事件处理程序提供了一组接口,分别对应于不同类型的事件;当有事件发生时, R e a c t o r Reactor Reactor调用相应的事件处理函数,通常会绑定一个有效的句柄。

对应到 l i b e v e n t libevent libevent,就是 e v e n t event event结构体。

常用的 E v e n t Event Event H a n d l e Handle Handle声明:

class Event_Handle{
public:
	virtual void handle_read() = 0; 
	virtual void handle_write() = 0; 
	virtual void handle_timeout() = 0; 
	virtual void handle_close() = 0; 
	virtual HANDLE get_handle() = 0; 
	// ... 
};
class Event_Handle{
public:
	// events maybe read/write/timeout/close .etc 
	virtual void handle_events(int events) = 0; 
	virtual HANDLE get_handle() = 0; 
	// ... 
};

5. R e a c t o r Reactor Reactor事件处理流程
如下图:

libevent源码分析(二) Reactor模式_第2张图片
6.与 P r o a c t o r Proactor Proactor模式区别

  • (1) R e a c t o r Reactor Reactor模式是基于同步 I / O I/O I/O的,而 P r o a c t o r Proactor Proactor则是基于异步 I / O I/O I/O

  • (2)上面我们提到 R e a c t o r Reactor Reactor模式是应用程序注册事件到 R e a c t o r Reactor Reactor,然后当事件发生时, R e a c t o r Reactor Reactor调用其回调函数进行事件处理,由回调函数来进行读写等操作;而在 P r o a c t o r Proactor Proactor模式中,事件处理者直接发起一个异步读写操作(相当于请求),而实际的工作由操作系统完成。

  • (3)两种模式的处理步骤
    标准的 R e a c t o r Reactor Reactor步骤:
    1)等待事件( R e a c t o r Reactor Reactor完成)
    2)将”就绪”事件发给事件注册的事件处理者或者回调函数( R e a c t o r Reactor Reactor完成)
    3)读数据(用户完成)
    4)处理数据(用户完成)
    模拟的 P r o a c t o r Proactor Proactor步骤:
    1)等待事件( P r o a c t o r Proactor Proactor完成)
    2)读数据( P r o a c t o r Proactor Proactor完成)
    3)把数据准备好的消息传给事件处理者( P r o a c t o r Proactor Proactor完成)
    4)处理数据(用户完成)

  • (4)两者区别
    1. R e a c t o r Reactor Reactor模式更多的是关心事件的发生,将如何处理事件的后续交给了用户态的应用来处理;而 P r o a c t o r Proactor Proactor则☞关心由操作系统完成异步非阻塞操作之后的结果
    2. P r o a c t o r Proactor Proactor场景中只能够使用异步非阻塞的 s y s c a l l syscall syscall(系统调用),而 R e a c t o r Reactor Reactor的场景中更多地是使用非阻塞同步的 s y s c a l l syscall syscall(系统调用);

参考文章:关于Reactor和Proactor的区别
libevent源码深度剖析二

你可能感兴趣的:(libevent源码分析)