最近研究 Java NIO 的时候,常常看到一种 设计模式——Reactor模式,以前没接触过这个模式在Netty中也有应用,那么Reactor模式是什么?为什么要使用Reactor模式?在NIO中如何实现Reactor模式?下面将揭开 Reactor的神秘面纱
下面的介绍参考了网上很多相关资料,所以会与网上某些资料有重复的情况,还请见谅
Reactor 是一种和 IO 相关的设计模式,Java中的NIO中天生就对 Reactor模式提供了很好的支持,比较著名的就是Doung Lea 大神在 《Scalable IO in Java》 演示如何使用 NIO 实现Reactor模式
在维基百科上对 Reactor模式定义如下:
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers
从上面的描述我们可以得到几个关键点:
在 netty学习系列二:NIO Reactor模型 & Netty线程模型 这篇文章谈到,Reactor实际上采用了 分而治之 和 事件驱动 的思想:
分而治之: 一个连接里完整的网络处理过程一般分为 accept,read,decode,process,encode,send这几步。而Reactor模式将每个步骤映射为 一个Task,服务端线程执行的最小逻辑单元不再是一个完整的网络请求,而是 Task,且采用非阻塞方式执行。
事件驱动: 每个Task 对应特定的网络事件,当Task 准备就绪时,Reactor 收到对应的网络事件通知,并将Task 分发给绑定了对应网络事件的 Handler 执行。
总结以上几个特点,再次说明下 Reactor模式就是 指一个或多个事件输入同时传递给服务处理器(Reactor),服务处理器负责监听各事件的状态,当任意一个事件准备就绪时,服务处理器收到该事件通知,并将事件发送给绑定了该对应网络事件的事件处理器(Handler)执行
Reactor模式也叫做Dispatcher模式,即 I/O多路复用统一监听事件,收到事件后再分发(Dispatch)给相应的处理线程。
谈到 Reactor模式就会让我想起观察者模式,它俩看起来非常相似的,但是观察者模式主要用于 一对多 的情况,它定义了一个一对多的依赖关系,让多个观察者对象监听一个主题对象,当被观察者状态改变时,需要通知相应的观察者,使这些观察者能够自动更新。所以 实际上它们还是有不同的,观察者模式与单个事件源关联,而Reactor模式与多个事件源关联 。
以下的说明参考了Alibaba资深技术专家李运华的极客时间专栏从0开始学架构中对于Reactor的介绍
Reactor模式有三种典型的实现方案:
在介绍三个方案之前,先来了解下Reactor模式中的几个角色:
PS: 以上的select,accept,read,send是标准I/O复用模型的网络编程API,dispatch和"业务处理"是需要完成的操作。
方案的具体步骤如下: