最近学习NIO,看《Netty权威指南》的时候,讲JDK1.5的NIO提到了Reactor模式。

我到网上看了一下,发现Reactor模式一开始在ACE(AdaptiveCommunication Environment是一个跨平台的用于并发通信的C++框架)中提得比较多。用于同步非阻塞的网络通讯,简化了事件驱动程序的开发,允许事件驱动的应用对源自许多不同事件源的事件做出反应,如I/O句柄,定时器,以及信号。

在JDK还没有引入NIO的时候,在网络编程中只能使用BIO(同步阻塞),Server先accept多个Client来的请求,然后分别分配一个Thread来处理一个请求。如Tomcat5.0就是使用这种方式来处理客户端请求(Connector/Processor),只是使用了线程池来进一步优化。

在引入NIO后,通过多路复用器Selector来实现非阻塞的Socket通讯,这时Reactor模式有了用武之地。

Reactor模式

在分布式系统尤其是服务器这一类事件驱动应用中,需要处理多个同时到来的请求,而且这些请求具有多个不同的状态,如何才能有序高效地处理这些请求要求我们满足以下几点:

l   为了提高系统的可测量性和反应时间,应用程序不能长时间阻塞在某个事件源上而停止对其他事件的处理,这样会严重降低对客户端的响应度。

l   为了提高吞吐量,任何没有必要的上下文切换、同步和CPU之间的数据移动都要避免。

l   引进新的服务或改良已有的服务都要对既有的事件分离和调度机制带来尽可能小的影响。

l   大量的应用程序代码需要隐藏在复杂的多线程和同步机制之后。

为了解决这些问题,我们需要将不同事件分离出来,不同的事件由不同的Handler来处理,一个Handler只处理一种类型的事件;而且把事件的调度分派和处理分离开来,由一个管理中心统一分配和调度。

Reactor(反应器)就是这个统一的管理中心,负责接收客户请求,分离(demultiplex)不同的事件,并调度(dispatch)给相应的应用程序(Handler)来处理。

在Reactor模式中,有5个关键的参与者:

1.        描述符/操作数(Handle):由操作系统提供,用于识别每一个事件,如Socket描述符、文件描述符等。在Linux中,它用一个整数来表示。事件可以来自外部,如来自客户端的连接请求、数据等。事件也可以来自内部,如定时器事件。

2.        同步事件分离器(Demultiplexer):是一个函数,用来等待一个或多个事件的发生。调用者会被阻塞,直到分离器分离的描述符集上有事件发生。Linux的select函数是一个经常被使用的分离器。

3.        事件处理器接口(EventHandler):是由一个或多个模板函数组成的接口。这些模板函数描述了和应用程序相关的对某个事件的操作。

4.        具体的事件处理器(Handler):是事件处理器接口的实现。它实现了应用程序提供的某个服务。每个具体的事件处理器总和一个描述符相关。它使用描述符来识别事件、识别应用程序提供的服务。

5.        Reactor 管理器(Reactor):定义了一些接口,用于应用程序控制事件调度,以及应用程序注册、删除事件处理器和相关的描述符。它是事件处理器的调度核心。 Reactor管理器使用同步事件分离器来等待事件的发生。一旦事件发生,Reactor管理器先是分离每个事件,然后调度事件处理器,最后调用相关的模板函数来处理这个事件。

通过上述分析,我们注意到,是Reactor管理器而不是应用程序负责等待事件、分离事件和调度事件。实际上,Reactor管理器并没有被具体的事件处理器调用,而是管理器调度具体的事件处理器,由事件处理器对发生的事件做出处理。这就是类似Hollywood原则的“反向控制”。应用程序要做的 仅仅是实现一个具体的事件处理器,然后把它注册到Reactor管理器中。接下来的工作由管理器来完成。

Java中的Reactor模式

在Java中Reactor模式的实现要结合NIO的Selector。例如在一个服务器对应多个客户端的场景下,先初始化ServerSocketChannel绑定端口并设置成非阻塞模式;然后把ServerSocketChannel注册到Selector中,监听SelectionKey.OP_ACCEPT操作位;最后在run()中循环遍历Selector,取出就绪的Channel分派给响应的Handler处理即可。

public class Reactor implements Runnable {public final Selector selector;public final ServerSocketChannel serverSocketChannel;public Reactor(int port) throws IOException {selector = Selector.open();serverSocketChannel =ServerSocketChannel.open();InetSocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);serverSocketChannel.socket().bind(inetSocketAddress);serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);}public void run() {try {while (!Thread.interrupted()) {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> it = selectionKeys.iterator();while (it.hasNext()) {SelectionKey selectionKey = it.next();dispatch(selectionKey);selectionKeys.clear();}}} catch (IOException e) { e.printStackTrace(); }}void dispatch(SelectionKey key) {}
}

上面的反应器Reactor,通过分离器Selector来监听不同事件(操作数),然后把监听到的事件分派给相应的Handler处理,充当着管理调度中心的角色。

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

参考:《Netty权威指南》和博文http://www.cnblogs.com/hzbook/archive/2012/07/19/2599698.html

Reactor反应器模式相关推荐

  1. 反应器(Reactor)模式-golang探索

    反应器模式 在以前的博文模式设计概述:反应器(Reactor)模式介绍过相关的概念和流程,当时使用了python但是从结果上来看并没有起到很明显的效果.最近在处理有关proxy的项目中,刚刚好涉及到有 ...

  2. Reactor模式:反应器模式

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

  3. 模式设计概述:反应器(Reactor)模式

    事件处理模式 在<面向模式的软件体系架构卷2:用于并发和网络化对象模式>中,总结了对于当前比较流行的事件处理模式的四种基本模式,分别是反应器模式.主动器模式.异步完成标记和接收器-连接器模 ...

  4. Reactor构架模式--转载

    原文:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece76310468a3b404380143c86964868d4e419ce3b464 ...

  5. Reactor构架模式

    2.1  Reactor构架模式 对每一个构架模式的分析,我们都使用参考文献的分析风格,着重分析意图.上下文.问题.解决方案.结构和实现 6个方面的内容.而实现就是ACE源代码. 1. 意图 在事件驱 ...

  6. 反应堆模式(reactor)

    在提到高性能服务器编程的时候肯定有听过reactor模式,如果只是简单的写一个服务器和客户端建立连接的程序来熟悉一下使用socket函数编程,一般这种情况都是同步方式实现的,服务器阻塞等待客户端的连接 ...

  7. I/O多路复用——Reactor模式

    2019独角兽企业重金招聘Python工程师标准>>> 一.概述 Reactor反应器模式是一个事件驱动,有一个或多个并发源,有一个业务处理器和多个请求处理器的模式,如图 假设一个场 ...

  8. 一步步Netty的基石 - Reactor模式

    1.NIO实现Client-Server通讯 我们将NIO实现Client-Server通讯的流程分为4步,见下面伪代码: class NioServer{ main(){初始化 nio 相关组件fo ...

  9. java reactor 模式_Reactor模式

    备注: 文章很长,建议收藏起来,慢慢读! 并且,持续更新中- 高薪必备1 : <Netty Zookeeper Redis 高并发实战> 为你打造NIO.Netty 高性能底层原理知识底座 ...

  10. Java I/O中的Reactor模式

    传统I/O模式 我们之前的的I/O文章中有过如下这种图: 如上模型中,存在的问题 当并发数量很大的时候,会创建大量的线程,占用很大的系统资源 当连接创建后,如果当前线程暂时没有可以读的数据,那么改县城 ...

最新文章

  1. 命令查看多线程所有线程ID
  2. 实战SSM_O2O商铺_46【Redis缓存】头条信息+商铺目录Service层加入缓存
  3. 我在阿里云做前端代码智能化
  4. Python __subclasses__() 函数获取类的所有子类
  5. Android.mk中的LOCAL_OVERRIDES_PACKAGES
  6. 色彩缤纷的python(改变字体颜色及样式不完全版)
  7. 阶段3 1.Mybatis_03.自定义Mybatis框架_4.自定义mybatis的编码-解析XML的工具类介绍
  8. greenDaoMaster的学习研究
  9. HTTP请求协议格式详解
  10. 参加第四届高校程序设计大赛-团体程序设计天梯赛心得
  11. 使用Cloudflare API动态解析域名IP
  12. 无线路由器的五种工作模式
  13. 谷歌浏览器插件 - 为 Microsoft Bing 搜索引擎首页添加一个【保存背景图片】的按钮(版本 1)
  14. 新浪微博模拟登陆passwd参数rsa解密
  15. Rust - 常用的三方库集合
  16. windows 10目标文件夹访问被拒绝(没有权限)或者(你需要来自XXX的权限才能对此文件夹进行更改 )
  17. 忧桑三角形,调了半天,真忧桑TAT
  18. Python表白妙招,把情书写进她的照片里
  19. 想创业成功?先看看这25家千亿美金的公司是如何炼成的!
  20. python怎么读excel_python怎么读写excel文件

热门文章

  1. 2.3 pandas:汇总和计算描述统计(统计上的方法)
  2. vue实现手机验证码登录
  3. 多个文本对比相似度分析
  4. 2022IEOC全国赛专业组获奖及晋级成绩公布 全球赛期待继续辉煌
  5. 联通服务器光信号亮红灯移动,光纤猫los红灯闪什么原因
  6. 高速公路联网收费ETC设备可维护性技术要求(征求意见)
  7. 雅思两次7.5经验分享~希望帮你冲击雅思高分!
  8. 树莓派安装MPlayer播放器
  9. 一些框架图的色彩搭配
  10. 计算机类绘图的文献,绘图计算机论文,关于机械制图计算机绘图的有效融合相关参考文献资料-免费论文范文...