Netty和Redis都在用的Recator设计模式到底是个啥?

Reactor设计模式

目录大纲
Netty和Redis都在用的Recator设计模式到底是个啥?_第1张图片

Reactor是什么

Reactor设计模式是一种事件驱动模式,用于处理通过一个或多个输入并发地传递给服务处理程序的服务请求。然后,服务处理程序对传入的请求进行多路复用,并将它们同步地分派给相关的请求处理程序

Netty和Redis都在用的Recator设计模式到底是个啥?_第2张图片

虽然上图很low,不过可以看到一个基本的框架,下面讲一下具体里面的属性概念

OMT 类图设计

Netty和Redis都在用的Recator设计模式到底是个啥?_第3张图片

  • Handle:Handle是事件产生的发源地
  • Synchronous Event Demultiplexer(同步事件分离器):I/O多路复用机制,比如Linux中的select,epoll,java NIO中是Selector选择器,他会阻塞的等待事件的发生
  • Event Handler(事件处理器):多个回调方法的结合体,事件的反馈机制,在Java NIO领域中并没有提供事件处理器机制让我们调用或去进行回调,所以nio需要我们自己实现Reactor模式
  • Concrete Event Handler(具体事件处理器):是事件处理器的实现。
  • Initiation Dispatcher(初始分发器):Dispatcher会通过I/O多路复用机制来等待事件的发生。一旦事件发生,Dispatcher首先会分离出每一个事件,然后调用事件处理器,最后调用相关的回调方法来处理这些事件。
  • Handle(句柄或描述符,在Windows下称为句柄,在Linux下称为描述符):本质上表示一种资源(比如说文件描述符,或是针对网络编程中的socket描述符),是由操作系统提供的;该资源用于表示一个个的事件,事件既可以来自于外部,也可以来自于内部;外部事件比如说客户端的连接请求,客户端发送过来的数据等;内部事件比如说操作系统产生的定时事件等。它本质上就是一个文件描述符,Handle是事件产生的发源地。
  • Synchronous Event Demultiplexer(同步事件分离器):它本身是一个系统调用,用于等待事件的发生(事件可能是一个,也可能是多个)。调用方在调用它的时候会被阻塞,一直阻塞到同步事件分离器上有事件产生为止。对于Linux来说,同步事件分离器指的就是常用的I/O多路复用机制,比如说select、poll、epoll等。在Java NIO领域中,同步事件分离器对应的组件就是Selector;对应的阻塞方法就是select方法。
  • Event Handler(事件处理器):本身由多个回调方法构成,这些回调方法构成了与应用相关的对于某个事件的反馈机制。在Java NIO领域中并没有提供事件处理器机制让我们调用或去进行回调,是由我们自己编写代码完成的。Netty相比于Java NIO来说,在事件处理器这个角色上进行了一个升级,它为我们开发者提供了大量的回调方法,供我们在特定事件产生时实现相应的回调方法进行业务逻辑的处理,即,ChannelHandler。ChannelHandler中的方法对应的都是一个个事件的回调。
  • Concrete Event Handler(具体事件处理器):是事件处理器的实现。它本身实现了事件处理器所提供的各种回调方法,从而实现了特定于业务的逻辑。它本质上就是我们所编写的一个个的处理器实现。
  • Initiation Dispatcher(初始分发器):实际上就是Reactor角色。它本身定义了一些规范,这些规范用于控制事件的调度方式,同时又提供了应用进行事件处理器的注册、删除等设施。它本身是整个事件处理器的核心所在,Initiation Dispatcher会通过Synchronous Event Demultiplexer来等待事件的发生。一旦事件发生,Initiation Dispatcher首先会分离出每一个事件,然后调用事件处理器,最后调用相关的回调方法来处理这些事件。Netty中ChannelHandler里的一个个回调方法都是由bossGroup或workGroup中的某个EventLoop来调用的。

ok,说完了Reactor里面的几个属性概念,你应该知道了这个模型里大概有点什么东西,那么我们看一下他的几种流程模式

流程模式

单线程模式

Netty和Redis都在用的Recator设计模式到底是个啥?_第4张图片

Reactor: 是一个线程对象,该线程会启动事件循环,并使用Selector来实现IO的多路复用,当Reactor监听到事件发生时,将相关的事件派发给对应的处理器(Handlers )进行处理

Acceptor: Acceptor事件处理器所关注的事件是accept事件,监听到accept事件后,将该连接所关注的事件和事件处理器注册到Reactor上,这样Reactor就会监听这个事件

Handlers: 执行非阻塞读/写 任务


多线程模式

Netty和Redis都在用的Recator设计模式到底是个啥?_第5张图片

多线程在单线程的基础上使用了线程池,获取到IO的读写事件之后,交由线程池来处理,这样可以减小主reactor的性能开销,从而更专注的做事件分发工作了,从而提升整个应用的吞吐。

多Reactor模式
Netty和Redis都在用的Recator设计模式到底是个啥?_第6张图片

对于多个CPU的机器,为充分利用系统资源将其拆成两个模块MainReactor和subReactor,MainReactor可以只有一个,但subReactor一般会有多个

MainReactor负责监听连接,用来处理新连接的建立,subReactor处理请求做数据交互和事件业务处理操作,此模型下每个模块的工作更加专一,耦合度更低,性能和稳定性也大量的提升

关于应用

Netty采用的就是典型的Reactor设计模型

Redis中有两类事件

文件事件,如get命令

时间事件,如定时rdb持久化

参考《Redis的设计与实现》,Redis的文件事件处理模型是这样的:

Netty和Redis都在用的Recator设计模式到底是个啥?_第7张图片
在文件事件中,Redis的主线程采用IO多路复用技术,文件事件分派,及事件处理器,采用的就是Reactor模式

另外我这有一份关于java的面试题,大家可以关注我的公众号(在最下方!),回复:【java面试题】 来领取

java面试题

你可能感兴趣的:(IO,设计模式)