NIO界最强“Hello World”,不服来辩

不知道大家有没有发现面向网络编程的框架都非常突出线程模型,其实也不难理解,因为网络编程是IO密集型,合理使用线程对提高性能有着非常显著的作用。

在网络编程模型中,有一个非常经典的线程模型:主从多Reactor模型,其示意图如下所示:

在这里插入图片描述

我们首先简单介绍一下上图中涉及的几个重要角色:

  • Acceptor

请求接收者,在实践时其职责类似服务器,并不真正负责连接请求的建立,而只将其请求委托 Main Reactor 线程池来实现,起到一个转发的作用。

  • Main Reactor

主 Reactor 线程组,主要负责连接事件,并将IO读写请求转发到 SubReactor 线程池。当然在一些需要对客户端进行权限控制等场景下,权限校验的职责可以放到 Main Reactor 线程池,即 Main Reactor 也可以注册通道的读写事件,读取客户端权限校验相关的数据包,执行权限验证,权限验证通过后再将2通道注册到IO线程。

  • Sub Reactor

Main Reactor 通常监听客户端连接后会将通道的读写转发到 Sub Reactor 线程池中一个线程(负载均衡),负责数据的读写。在 NIO 中 通常注册通道的读(OP_READ)、写事件(OP_WRITE)。

上面的图非常经典,除了介绍了线程模型相关知识外,其实还罗列出了网络通信的核心步骤:

  • 编码/解码(通信协议)

  • 认证授权

  • 网络读、写

  • 业务逻辑处理线程池

上述的线程模型非常经典,那我们能否基于NIO,来模拟实现上面的线程模型呢?

2、基于NIO实现主从多Reactor模型


我听一个技术圈大佬对我说过这样一句话:NIO是一名程序员进阶的第一个门槛,也是必需跨过的门槛。

笔者将尝试用NIO实现Reactor模型,成为NIO界最强的"Hello Wold"

为了接下来的代码进行展示与讲解,首先先罗列出其核心类图:

在这里插入图片描述

各个类的职责说明情况如下:

  • Acceptor

服务端接收器,主要绑定端口,将ServerSocketChannel转发到MainReactor,及主从多Reactor模型中的主Reactor中。如果服务端绑定多个端口,则会创建多个ServerSocketChannel,但通常情况只会绑定到一个端口。

  • MainReactor

主Reactor,主要承担接受客户端的连接请求,即主要负责OP_ACCEPT事件的处理,并将创建的连接(SocketChannel)转发到从Reactor线程组,由其处理读写事件

  • SubReactorThreadGroup

从Reactor线程组,维护多个Reactor线程,并提供负载均衡。

  • SubReactorThread

从Reactor,主要负责IO读写,俗称IO线程。

在上源码之前我们再来看一下整个示例到时序图:

在这里插入图片描述

核心的关键点如下:

  • Acceptor主要是创建ServerSocketChannel,然后转发给MainReactor

  • MainReactor中维护一个NIO Selector事件选择器,注册OP_ACCEPT事件,每处理一个OP_ACCEPT,表示一个新的客户端连接,在服务端会创建一个SocketChannel对象,接着将该对象转发到从Reactor

  • SubReactorThreadGroup

主从多Reactor模型中的从Reactor组,包含多个从Reactor线程,新的连接会进行负载均衡,选择其中一个Reactor来处理特定的SocketChannel。

  • SubReactorThread

从Reactor线程,会维护一个Nio Selector,会将SocketChannel注册到该事件选择器,处理读、写请求,一个Selector中会包含多个Channel(SocketChannel),但一个SocketChannel在其生命周期中只会注册到一个Selector,这样可以简化处理模型。

程序员希望不服就干,接下来我将展示基于NIO实现多Reactor的代码,应该是全网目前第一个直接用代码实现。

温馨提示:为了便于排版,本文中的代码统一用截图进行展示,代码获取方式:私信回复 reactorcode 即可获取。

[](

)2.1 Acceptor代码实现

Acceptor代码实现如下:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210717194702494.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ByZXN0aWdlZGluZw==,size_16,co 需要zi料+ 绿色徽【vip1024b】

lor_FFFFFF,t_70#pic_center)

Acceptor代码实现比较简单,就是利用NIO提供的API创建ServerSocketChannel,并设置为非阻塞模式,并调用bind方法绑定端口,然后转发到MainReactor中。

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

[外链图片转存中…(img-Ra8Cu5co-1710363824457)]

[外链图片转存中…(img-LxXVEFj9-1710363824458)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值