[libevent]Reactor反应器设计模式

对象行为类的设计模式,对同步事件分拣和派发。别名Dispatcher(分发器)

Reactor模式是处理并发I/O比较常见的一种模式,用于同步I/O,中心思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上;一旦有I/O事件到来或是准备就绪(区别在于多路复用器是边沿触发还是水平触发),多路复用器返回并将相应I/O事件分发到对应的处理器中。

Reactor的事件处理机制

普通函数调用的机制:程序调用某函数->函数执行,程序等待->函数将结果和控制权返回给程序->程序继续处理。而所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数)。

事件驱动模型

Reactor释义“反应堆”,是一种事件驱动机制。和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。使用Libevent也是向Libevent框架注册相应的事件和回调函数;当这些时间发声时,Libevent会调用这些回调函数处理相应的事件(I/O读写、定时和信号)。

Reactor模式与Observer模式在某些方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联 。

Reactor模式的优点

Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:

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

Reactor模式框架

使用Reactor模型,必备的几个组件:事件源、Reactor框架、多路复用机制和事件处理程序

Reactor模型的整体框架

Reactor模型UML

  • Handle事件源

Handle代表操作系统管理的资源,包括:网络链接,打开的文件,计时器,同步对象等等。Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。

  • event demultiplexer——事件多路分发机制

由操作系统提供的I/O多路复用机制,比如select和epoll。程序首先将其关心的句柄(事件源)及其事件注册到event demultiplexer上;

当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”;程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。 对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外隐藏底层系统机制的目的。

事件分离器,由操作系统提供,在linux上一般是select, poll, epoll等系统调用,在一个Handle集合上等待事件的发生。接受client连接,建立对应client的事件处理器(Event Handler),并向事件分发器(Reactor)注册此事件处理器.

  • Reactor——反应器

Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。

提供接口:注册,删除和派发Event Handler。Event Demultiplexer等待事件的发生,当检测到新的事件,就把事件交给Initiation Dispatcher,它去回调Event Handler。

对应到libevent中,就是event_base结构体。一个典型的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);
// ...
}; 
  • Event Handler——事件处理程序

事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。通常它会绑定一个有效的句柄。

事件处理器,负责处理特定事件的处理函数。一般在基本的Handler基础上还会有更进一步的层次划分,用来抽象诸如decode,process和encoder这些过程。比如对Web Server而言,decode通常是HTTP请求的解析,process的过程会进一步涉及到Listner和Servlet的调用。为了简化设计,Event Handler通常被设计成状态机,按GoF的state pattern来实现。对应到libevent中,就是event结构体。下面是两种典型的Event Handler类声明方式,二者互有优缺点。

class Event_Handler
{
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_Handler
{
public:
// events maybe read/write/timeout/close .etc
virtual void handle_events(int events) = 0;
virtual HANDLE get_handle() = 0;
// ...
}; 
  • Concrete Event Handler

继承上面的类,实现钩子方法。应用把Concrete Event Handler注册到Reactor,等待被处理的事件。当事件发生,这些方法被回调。

应用场景举例

场景:长途客车在路途上,有人上车有人下车,但是乘客总是希望能够在客车上得到休息。

传统做法:每隔一段时间(或每一个站),司机或售票员对每一个乘客询问是否下车。

Reactor做法:汽车是乘客访问的主体(Reactor),乘客上车后,到售票员(acceptor)处登记,之后乘客便可以休息睡觉去了,当到达乘客所要到达的目的地后,售票员将其唤醒即可。

时间: 2024-10-23 09:55:33

[libevent]Reactor反应器设计模式的相关文章

JAVA设计模式——观察者设计模式和Reactor反应堆设计模式

被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一个观察者 public void addWatcher(Watcher watcher); //删除一个观察者 public void removeWatcher(Watcher watcher); //通知所有的观察者 public void notifyWatchers(String str);

Reactor反应器模式

最近学习NIO,看<Netty权威指南>的时候,讲JDK1.5的NIO提到了Reactor模式. 我到网上看了一下,发现Reactor模式一开始在ACE(AdaptiveCommunication Environment是一个跨平台的用于并发通信的C++框架)中提得比较多.用于同步非阻塞的网络通讯,简化了事件驱动程序的开发,允许事件驱动的应用对源自许多不同事件源的事件做出反应,如I/O句柄,定时器,以及信号. 在JDK还没有引入NIO的时候,在网络编程中只能使用BIO(同步阻塞),Server

libevent之Reactor模式

通过前边的一篇博文轻量级网络库libevent初探,我们知道libevent实际上是封装了不同操作系统下的/dev/poll.kqueue.event ports.select.poll和epoll事件机制,从而给我们提供一个统一的接口. libevent采用了Reactor I/O 设计模式,而Reactor是基于同步I/O机制的,所以libevent实际是一个基于同步I/O机制的库. 对于I/O设计模式,与Reactor相对应的还有Proactor.下边我们先来看下这两者的不同之处. Rea

reactor模型框架图和流程图 libevent

学习libevent有助于提升程序设计功力,除了网络程序设计方面外,libevent的代码里有很多有用的设计技巧和基础数据结构,比如信息隐藏.函数指针.c语言的多态支持.链表和堆等等,都有助于提升自身的程序功力.       程序设计不止要了解框架,很多细节之处恰恰也是事关整个系统成败的关键.只对libevent本身的框架大概了解,那或许仅仅是一知半解,不深入代码分析,就难以了解其设计的精巧之处,也就难以为自己所用.       事实上libevent本身就是一个典型的Reactor模型,理解R

C++服务器设计(一):基于I/O复用的Reactor模式

I/O模型选择 在网络服务端编程中,一个常见的情景是服务器需要判断多个已连接套接字是否可读,如果某个套接字可读,则读取该套接字数据,并进行进一步处理. 在最常用的阻塞式I/O模型中,我们对每个连接套接字通过轮流read系统调用获取可读数据.如图3-1所示,read系统调用将会把该线程阻塞,直到数据报到达且被复制到应用进程的缓冲区中时才会返回. 图3-1 阻塞式I/O模型 在阻塞式I/O模型中,数据可读和读取数据这两个操作被合并在了一个系统调用中,对于单个套接字是否可读的判断,必须要等到实际数据接

Reactor模式

对象行为类的设计模式,对同步事件分拣和派发.别名Dispatcher(分发器) Reactor模式是处理并发I/O比较常见的一种模式,用于同步I/O,中心思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上:一旦有I/O事件到来或是准备就绪(区别在于多路复用器是边沿触发还是水平触发),多路复用器返回并将相应I/O事件分发到对应的处理器中. Reactor的事件处理机制 普通函数调用的机制:程序调用某函数->函数执行,程序等待->函数将结果和控制权返回给程

libevent(了解)

1 前言 Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少.写这一系列文章的用意在于,一则分享心得:二则对libevent代码和设计思想做系统的.更深层次的分析,写出来,也可供后来者参考. 附带一句:Libevent是用c语言编写的(MS大牛们都偏爱c语言哪),而且几乎是无处不函数指针,学习其源代码也需要相当的c语言基础. 2 LIBEVENT简介 上来当然要先夸奖啦,Libevent 有几个显著的亮点:事件驱动(event-driven),高性能;轻量级,

使用 libevent 和 libev 提高网络应用性能——I/O模型演进变化史

构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接,都要有效地处理它们的操作. 有许多解决方案,但事件驱动也被广泛应用到网络编程中.并大规模部署在高连接数高吞吐量的服务器程序中,如 http 服务器程序.ftp 服务器程序等.相比于传统的网络编程方式,事件驱动能够极大的降低资源占用,增大服务接待能力,并提高网络传输效率. 这些事件驱动模型中, libevent 库和 libev库能够大大提高性能和事件处理能力.在本文中,我们要讨论在 UNIX/

libevent学习笔记 一、基础知识

欢迎转载,转载请注明原文地址:http://blog.csdn.net/majianfei1023/article/details/46485705 一.libevent是什么 libevent是一个轻量级的开源的高性能的事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制. 它被众多的开源项目使用,例如大名鼎鼎的memcached等. 特点: 事件驱动,高性能; 轻量级,专注于网络(相对于ACE); 开放源码