IO模型与Reactor模型

1. 服务端处理网络请求

IO模型与Reactor模型_第1张图片

 

2. 5种I/O模型比较

IO模型与Reactor模型_第2张图片

 

I/O 复用与阻塞式I/O 相比并不是对于单个线程处理的更快,而是在于能处理多个连接

Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理

3. 线程模型

3.1 单线程Reactor模式

IO模型与Reactor模型_第3张图片

 

(1)其中客户端发送请求至服务端,Reactor响应其IO事件。

(2)如果是建立连接的请求,则将其分发至acceptor,由其接受连接,然后再将其注册至分发器。

(3)如果是读请求,则分发至Handler,由其读出请求内容,然后对内容解码,然后处理计算,再对响应编码,最后发送响应。

 

3.2 多线程Reactor模式

IO模型与Reactor模型_第4张图片

 

 

3.3 多Reactor模式

IO模型与Reactor模型_第5张图片

 

其中主Reactor响应用户的连接事件,然后分发给acceptor,由其创建新的子Reactor。多个子Reactor分别处理各自的IO事件,比如read/write,然后再将其交给work thread pool进行解码,业务处理,编码。

3.4 Netty中线程模型

Netty中有EventLoopGroup和EventLoop两个类,它们是实现Reactor的关键之所在。EventLoop正如其名,其中包包含一个Selector选择器和一段循环逻辑。通过不断循环获取Selector上的就绪事件然后进行处理。EventLoopGroup是包含一组EventLoop的组,通过其可以产生一个EventLoop。

在创建一个Server时都会创建两个EventLoopGroup,分别为boss和work。前者用户Main Reactor,后者用于Sub Reactor和WorkThreadPool。

每次Main Reactor通过Selector得到客户端建立连接的请求后,就从work EventLoopGroup中获取一个EventLoop,然后将建立的连接对应的Socket抽象SocketChannel绑定到EventLoop上,形成了新的Sub Reactor。

 

4. Netty工作架构

IO模型与Reactor模型_第6张图片

 

4.1 Boss NioEventLoop循环执行的任务

  1. 轮询accept事件。

(2)处理accept I/O事件,与Client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个Worker NioEventLoop的Selector上 。

(3)处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用eventloop.execute或schedule执行的任务,或者其它线程提交到该eventloop的任务。

4.2  Woker NioEventLoop循环执行的任务

(1)轮询read、write事件。

(2)处理I/O事件,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理。

(3)处理任务队列中的任务,runAllTasks。

4.3 任务队列中的task有3种典型使用场景

 

(1)用户程序自定义的普通任务

IO模型与Reactor模型_第7张图片

非当前reactor线程调用channel的各种方法 例如在推送系统的业务线程里面,根据用户的标识,找到对应的channel引用,然后调用write类方法向该用户推送消息,就会进入到这种场景。最终的write会提交到任务队列中后被异步消费。

IO模型与Reactor模型_第8张图片

 

(3) 用户自定义定时任务

IO模型与Reactor模型_第9张图片

5.4 ChannelPipeline

IO模型与Reactor模型_第10张图片

每一个ChannelPipeline一个Channel 包含了一个 ChannelPipeline, 而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表, 并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler。入站事件和出站事件在一个双向链表中,入站事件会从链表head往后传递到最后一个入站的handler,出站事件会从链表tail往前传递到最前一个出站的handler,两种类型的handler互不干扰

PS: 入站事件-读取数据 出站事件-服务端绑定端口、客户端连接、写数据

入站-Decode(数据反序列化)  出站-Eecode(数据序列化)

参考资料:

史上最全阿里 Java 面试题总结

【BIO,NIO与AIO的区别】

你可能感兴趣的:(JAVA基础知识)