reactor模型_单线程Reactor反应器模式

总体来说,Reactor反 应器模式有点儿类似事件驱动模式。

在事件驱动模式中,当有事件触发时,事件源会将事件dispatch分发到handler处理器进行事件处理。反应器模式中的反应器角色,类似于事件驱动模式中的dispatcher事件分发器角色。

前面已经提到, 在反应器模式中,有Reactor反应器和Handler处理器两个重要的组件:

(1) Reactor反应器:负责查询IO事件,当检测到一个I0事件,将其发送给相应的Handler处理器去处理。这里的IO事件,就是NIO中选择器监控的通道IO事件。

(2) Handler处理器:与I0事件 (或者选择键)绑定,负责I0事件的处理。完成真正的连接建立、通道的读取、处理业务逻辑、负责将结果写出到通道等。

什么是单线程Reactor反应器

什么是单线程版本的Reactor反应器模式呢?简单地说,Reactor反应器和Handers处理器处于一个线程中执行。它是最简单的反应器模型,如图4-1所示。

8a2c05b8f95c7385732feb90551551f2.png

基于JavaNIO,如何实现简单的单线程版本的反应器模式呢?需要用到SelectionKey选择键的几个重要的成员方法:

方法一: void atach(Object o)

此方法可以将任何的Java POJO对象,作为附件添加到SelectionKey实例,相当于附件属性的setter方法。这方法非常重要,因为在单线程版本的反应器模式中,需要将Handler处理器实例,作为附件添加到SelectionKey实例。

方法二: Object attachment()

此方法的作用是取出之前通过attach(Object o)添加到SelectionKey选择键实例的附件,相当于附件属性的getter方法,与attach(Object o)配套使用。

这个方法同样非常重要,当I0事件发生,选择键被select方法选到,可以直接将事件的附件取出,也就是之前绑定的Handler处理器实例,通过该Handler,完成相应的处理。

总之,在反应器模式中,需要进行attach和attachment结合使用:在选择键注册完成之后,调用attach方法,将Handler处理器绑定到选择键;当事件发生时,调用attachment方法,可以从选择键取出Handler处理器,将事件分发到Handler处理器中,完成业务处理。

单线程Reactor反应器的参考代码

Doug Lea在《Scalable I0 in Java》中,实现了一个单线程Reactor反应器模式的参考代码。这里,我们站在巨人的肩膀上,借鉴Doug Lea的实现,对其进行介绍。为了方便说明,对DougLea的参考代码进行--些适当的修改。具体的参考代码如下:

dbb812025b7db4dde311876b5168441c.png

在上面的代码中,设计了一个Handler处理器,叫作AcceptorHandler处理器,它是一个内部类。在注册serverSocket服务监听连接的接受事件之后,创建-一个AcceptorHandler新连接处理器的实例,作为附件,被设置(attach) 到了SelectionKey中

a85475ba03fe4ac67661cd7facc27d48.png

在IOHandler的构造器中,有两点比较重要:

(1)将新的SocketChannel传输通道,注册到了反应器Reactor类的同一个选择器中。这样保证了Reactor类和Handler类在同- -个线程中执行。

(2) Channel传输通道注册完成后,将IOHandler自 身作为附件,attach到 了选择键中。这样,在Reactor类分发事件(选择键)时,能执行到IOHandler的run方法。

如果上面的示例代码比较绕口,不要紧。为了彻底地理解个中妙处,自己动手开发一个可以执行的实例。下面基于 反应器模式,实现了一个EchoServer回显服务器实例。仔细阅读和运行这个实例,就可以明白上面这段绕口的程序代码的真正含义了。

一个 Reactor反应器版本的EchoServer实践案例

EchoServer回显服务器的功能很简单:读取客户端的输入,回显到客户端,所以也叫回显服务器。基于Reactor反应器模式来实现,设计3个重要的类:

(1)设计一个反应器类: EchoServerReactor类。

(2)设计两个处理器类: AcceptorHandler新连 接处理器、EchoHandler回 显处理器。

反应器类EchoServerReactor的实现思路和前面的示例代码基本.上相同,具体如下:

1cbbff64fed57ba0a74f01f9e2c111d8.png

以上两个类,是一个基于反应器模式的EchoServer回显服务器的完整实现。它是一个单线程版本的反应器模式,Reactor反 应器和所有的Handler处理器,都执行在同一条线程中。

运行EchoServerReactor类中的main方法,可以启动回显服务器。如果要看到回.显输出,还需要启动客户端。客户端的代码,在同一个包下,类名为EchoClient,负责数据的发送。打开源代码工程,直接运行即可。

单线程Reactor反 应器模式的缺点

单线程Reactor反应器模式,是基于Java的NIO实现的。相对于传统的多线程OIO,反应器模式不再需要启动成千上万条线程,效率自然是大大提升了。在单线程反应器模式中,Reactor反 应器和Handler处理器,都执行在同- -条线程上。这样,带来了一个问题:当其中某个Handler阻塞时,会导致其他所有的Handler都得不到执行。在这种场景下,如果被阻塞的Handler不仅仅负责输入和输出处理的业务,还包括负责连接监听的AcceptorHandler处理器。这个是非常严重的问题。为什么? 一旦AcceptorHandler处理器阻塞,会 导致整个服务不能接收新的连接,使得服务器变得不可用。因为这个缺陷,因此单线程反应器模型用得比较少。另外,目前的服务器都是多核的,单线程反应器模式模型不能充分利用多核资源。总之,在高性能服务器应用场景中,单线程反应器模式实际使用的很少。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值