Netty系列(二)Reactor模式详解

在正式进入Netty编程模型之前,还需要了解Reactor模式,因为netty就是基于Reactor模式做了一定的改进形成的netty模型。

一. 什么是Reactor模式

首先,Reactor是一种设计模式,不是具体的类,上篇文章中《Netty系列(一)java NIO详解及使用 Demo》,简单介绍了java NIO相关内容,其中的demo就是Reactor模式的一种最简单的实现。

实际上的Reactor模式,是基于Java NIO的,在他的基础上,抽象出来两个组件——Reactor和Handler两个组件:

  • Reactor:负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理;新的事件包含连接建立就绪、读就绪、写就绪等。
  • Handler:将自身(handler)与事件绑定,负责事件的处理,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。

如果要自己实现Reactor模式,其中的Reactor和Handler都是需要我们自定义的。

Reactor与Selector的关系?
它俩不是一个层面的东西,Reactor是一种模型,算是设计模式,也就是一种概念;Selector是java NIO包中的一个具体的类,实现Reactor模型,要用到selector这个类。真正实现的时候,我们还会自己创建一个Reactor(名字随意)类,这个类里面包含使用Selector工具类。

二. Reactor模式实现种类

Reactor大致有3种实现方式,每种都有它针对的使用场景,具体可以参考大佬的文档《Scalable IO in Java》

1.单Reactor单线程模式

在这里插入图片描述
或者看Scalable IO in Java中的图:
在这里插入图片描述
以上两个图是一个意思。如果熟悉NIO,上图很容易理解,不熟悉的话建议先看下上篇文章。

方案说明:

  1. Select 是前面 I/O 复用模型介绍的标准网络编程 API,可以实现应用程序通过一个阻塞对象监听多路连接请求;
  2. Reactor 对象,是我们自定义的,通过 Selector 监控客户端请求事件,收到事件后通过 Dispatch 进行分发;Dispatch我们一般会抽象出来一个方法或者一个类对象。
  3. 如果是建立连接请求事件,则由 Acceptor(自定义类对象)通过处理连接请求,然后创建一个 Handler(自定义对象)对象处理连接完成后的后续业务处理,比如read、decode、compute、encode、send;
  4. 如果不是建立连接事件,则 Reactor 会分发调用连接对应的 Handler 来响应;
  5. Handler 会完成 Read→业务处理→Send 的完整业务流程。

优缺点

  1. 优点:模型简单,没有多线程、进程通信、竞争的问题,全部都在一个线程中完成;
  2. 缺点: 性能问题,只有一个线程,无法完全发挥多核 CPU 的性能。Handler 在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈;
  3. 缺点:可靠性问题,线程意外终止,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障。

使用场景

客户端的数量有限,业务处理非常快速,比如 Redis在业务处理的时间复杂度 O(1) 的情况。

2.单Reactor多线程模式:

在这里插入图片描述
或者看Scalable IO in Java中的图:
在这里插入图片描述
以上两个图是一个意思。

方案说明:
与单线程版本相比,变化的地方是Handler部分,Handler的职责减轻了,

  1. handler 只负责响应事件,不做具体的业务处理, 通过read 读取数据后,会分发给后面的worker线程池的某个线程处理业务;
  2. worker 线程池会分配独立线程完成真正的业务,并将结果返回给handler;
  3. handler收到响应后,通过send 将结果返回给client。

优点: 可以充分的利用多核cpu 的处理能力。
缺点: 多线程数据共享和访问比较复杂,reactor 部分,使用单线程处理所有的事件的监听和响应,在高并发场景容易出现性能瓶颈。

3.主从Reactor多线程

在这里插入图片描述
或者看Scalable IO in Java中的图:
在这里插入图片描述
以上两个图是一个意思。

方案说明:

  1. Reactor主线程 MainReactor 对象通过select 监听连接事件, 收到事件后,通过Acceptor 处理连接事件;
  2. 当 Acceptor 处理连接事件后,MainReactor 将连接分配给SubReactor ;
  3. subreactor 将连接加入到连接队列进行监听,并创建handler进行各种事件处理;
  4. 当有新事件发生时, subreactor 就会调用对应的handler处理;
  5. handler 通过read 读取数据,分发给后面的worker 线程处理;
  6. worker 线程池分配独立的worker 线程进行业务处理,并返回结果;
  7. handler 收到响应的结果后,再通过send 将结果返回给client;
  8. Reactor 主线程可以对应多个Reactor 子线程, 即MainRecator 可以关联多个SubReactor。

优缺点:

优点:父线程与子线程的数据交互简单职责明确,父线程只需要接收新连接,子线程完成后续的业务处理。
优点:父线程与子线程的数据交互简单,Reactor 主线程只需要把新连接传给子线程,子线程无需返回数据。

缺点:编程复杂度较高

Netty就是基于主从reactor多线程模型改进来的。这种模型在许多项目中广泛使用,包括 Nginx 主从 Reactor 多进程模型,Memcached 主从多线程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值