Reactor模型你知道都有哪些吗?

以下的图片都来自Doug lea大神的《Scalable IO in Java》,也推荐大家去阅读下,就是对英文不好的小伙伴不太友好了,大家也可以看我的翻译版本,就是有些翻译的不太好,将就着看哈哈:Doug lea《Scalable IO in Java》翻译

系列文章

创作不易,如果对您有帮助,麻烦辛苦下小手点个关注,有任何问题都可以私信交流哈。
祝您虎年虎虎生威。

单Reactor 单线程模型

最基础的Reactor模型,指的是所有的I/O操作都在同一个NIO线程上完成。下图为线程模型:
在这里插入图片描述

Reactor模型使用的是异步非阻塞I/O,所有的I/O操作都不会导致阻塞,理论上一个县城可以独立处理所有IO操作,例如:通过Acceptor接收客户端的TCP连接请求消息,当连接建立完成后,通过Dispatch将对应的ByteBuffer派发到指定的Handler上进行消息的解码。用户线程消息编码后通过NIO线程发送给客户端。

适用场景:适用于处理器链中业务处理组件能快速完成的场景
缺点:对于高负载,大并发的应用场景不适合, 原因如下:

  • 一个NIO线程线程同时处理成百上千个连接,性能上无法支撑
  • 当NIO线程负载过重后,处理速度将变慢,这回导致大量客户端连接超时,消息挤压和处理超时,最终称为系统的性能瓶颈
  • 可靠性问题,一旦NIO线程意外died,会导致整个系统通信模块不可用,不能接收和处理消息

基于上边的这些问题,演进出了单Reactor多线程模型。


单Reactor 多线程模型

在这里插入图片描述

特点:

  • 有专门一个NIO线程——Acceptor线程用于监听服务端,接收客户端的TCP连接请求
  • 网络I/O操作——读、写等由一个NIO线程池负责,线程池可以使用JDK的线程池实现,它包含一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送响应
  • 一个NIO线程可用同时处理N条链路,但是一个连接只对应一个NIO线程,防止发生并发操作问题

这种单Reactor多处理线程的模型在绝大多数场景下可用满足性能需求,但是在个别特殊场景中,一个NIO线程负责监听和处理所有的客户端连接可能会存在性能问题,比如服务端需要对客户端进行安全认证,认证的过程又非常损耗性能,那就会出单点性能不足问题,因此又演进出了多Reactor多处理线程模型。


多Reactor 多线程模型

这种模型又被称为 “主从Reactor多线程模型”。在这里插入图片描述

第二种模型将事件处理放到了线程池中进行多线程处理,第三种模型是将Reactor的职责进行了划分,服接收客户端连接的不再是一个单独的NIO线程,而是一个独立的NIO线程池,分为了两部分:

  • mainReactor:负责监听ServerSocketChannel,用来处理客户端新连接的建立,并将建立的客户端的SocketChannel指定注册给subReactor
  • subReactor:维护自己的Selector,基于mainRactor建立的客户端的SocketChannel多路分离IO读写事件,读写网络数据,对于业务处理的功能,扔给worker线程池来完成

Netty的Reactor模型

客户端

EventLoopGroup group = new NioEventLoopGroup();
//这里使用的是Bootstrap,服务端使用的是ServerBootstrap
Bootstrap b = new Bootstrap();
  • Netty NIO客户端来说,仅创建一个EventLoopGroup
  • 一个EventLoop可以对应一个Reactor,EventLoopGroup可以理解为Reactor的分组
  • 一个Bootstrap的启动只能发起对一个远程地址的连接,所以只会使用一个NIO Selector,也就是说仅适用一个Reactor,即使,我们在声明使用一个EventLoopGroup,该EventLoopGroup也只会分配一个EventLoop对IO事件进行处理
  • 如果一个业务线程使用Netty NIO客户端,可以认为是“单Reactor单线程模型”
  • 如果有多个业务线程使用Netty NIO客户端,可以任务是“单Reactor多线程模型”
  • 同时我们可以创建多个Netty NIO客户端来实现“多Reactor多线程模型”



服务端

// 创建两个 EventLoopGroup 对象
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 创建 boss 线程组 用于服务端接受客户端的连接
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 创建 worker 线程组 用于进行 SocketChannel 的数据读写
// 创建 ServerBootstrap 对象
ServerBootstrap b = new ServerBootstrap();
// 设置使用的 EventLoopGroup
b.group(bossGroup, workerGroup);
  • 对于服务端,创建两个EventLoopGroup
    • bossGroup对应mainReactor,用于服务端接受客户端的连接,同时传入了线程数为1,表示只使用1个Reactor,那能不能boosGroup配置多个线程呢?是可以的,但是没有意义,一个服务端只能绑定一个端口,也就只能使用一个Selector处理客户端连接事件,即使配置多个线程,实际使用的也就1个
    • workerGroup对应subReactor,用于进行SocketChannel的数据读写
  • 如果EventLoopGroup未设置线程个数,默认为CPU核心数 * 2.

大家好,我是壹氿,感谢各位小伙伴点赞、收藏和评论,文章持续更新,我们下期再见!
也可以加我的个人VX交流沟通:lhj502819,一起努力冲击大厂,另外有很多学习以及面试的材料提供给大家。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

壹氿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值