java reactor 模式_Java网络学习必备:I/O模型和Reactor模式

“网络 I/O 在系统学习、性能优化和开发中越来越重要,本文带你了解 4 种 I/O 模型和 3 种 Reactor 模式”

I/O模型

下图所示,同步和异步,阻塞和非阻塞,两两结合一共有 4 种I/O模型

阻塞和非阻塞:根据程序是否阻塞自身运行来区分的。阻塞:应用程序在执行I/O操作后,如果没有获得响应,就会阻塞当前线程,不能执行其他任务。

非阻塞:是指应用程序在执行I/O操作后,不会阻塞当前的线程,可以继续执行其他的任务。

同步和异步:根据 I/O 响应的通知方式的不同。同步 I/O:收到 I/O 请求后,系统不会立刻响应应用程序;等到处理完成,系统才会通过系统调用的方式,告诉应用程序 I/O 结果。

异步 I/O:收到 I/O 请求后,系统会先告诉应用程序 I/O 请求已经收到,随后再去异步处理;等处理完成后,系统再通过事件通知的方式,告诉应用程序结果。

同步阻塞 (Synchronouse blocking I/O)

如上图所示,当应用程序发送读取数据的请求,内核接收到请求开始读取数据,一直到数据读完(或者遇到错误)返回给应用程序,应用程序一直是阻塞的。

这种场景应用程序阻塞是不占用CPU资源的。

同步非阻塞(Synchronous non-blocking I/O)

这里应用程序发送读取请求后,内核会立马返回( EAGAIN/EWOULDBLOCK ),表明数据还未就绪,稍后再试。这个时候就需要应用程序不断轮询,直到内核返回数据给应用程序。

这种方式是非常低效的,应用程序要不断轮询,需要占用 CPU 资源。并且这个时候如果内核已经读取完数据,然后程序的下一次轮询还未开始,这就会造成时间的浪费,对系统吞吐量造成影响。

异步阻塞(Asynchronous blocking I/O)

这里应用程序会将 socket 注册到 select 上,当应用程序调用 select 的时候就会被阻塞,而 Kernel 同时会监听 select 上的 socket 有数据可读 select 就会返回,然后程序读取数据。

这种方式的优势就在于可以处理大量的连接,对于连接数比较少的不一定比同步阻塞性能好。

在 Tomcat、Netty 中这种方式都叫做 NIO。也有叫 I/O 多路复用(I/O mutiplexing) ,这里 select 可以同时管理多个 socket ,对应 Linux 的实现有:select、poll、epoll

异步非阻塞(Asynchronous non-blocking I/O)

应用程序向内核请求读取数据,内核会立马告诉应用程序开始读取数据,然后应用程序可以处理其他事情。当内核读取完数据,并将数据 copy 到用户空间后,会通知应用程序数据已经读取完成。

这种模式一般我们也称作 AIO ,这种方式理论上比 NIO 要好,Netty 为什么不支持呢?(Netty 曾今支持过后来又移除了)AIO 在 Windows 上比较成熟,但很少用来做服务器。

AIO 在 Linux 下实现并不成熟。

Linux 下 AIO 先比较于 NIO 性能提升并不明显。

Reactor模式

在讲Reactor模式前,我们先回顾下传统的网络请求处理方式:

每接收一个客户端的请求,服务端都会创建一个线程来处理。

这种就是我们上面介绍的同步阻塞 I/O 模式,开发维护成本比较小,适合连接数比较少的服务。

既然每个请求分配一个线程不合适,怎样才能一个线程中处理多个请求?

我们可采用分治的思想,将处理流程拆分成更小的任务,减少每个线程的阻塞时间,基于事件驱动 (异步阻塞 I/O)。

接下来我们看看 Reactor 的定义Reactor:监听和分发 I/O 事件。

Handlers:处理分配的事件。

单线程 Reactor 模式

这里 Reactor 是单线程的,接收所有的客户端请求,连接请求分配给 acceptor,数据处理分配给处理的线程。

线程池处理业务逻辑

将业务处理线程与 I/O 处理拆分开,这样就可以避免 Reactor 线程由于业务处理造成阻塞,同样业务线程也不会受 Reactor 网络读取和发送的影响。

多个 ReactormainReactor:负责监听收客户端的连接。对应 Netty 中的 boosGroup,一般一个线程就够了。

subReactor:负责读取发送数据,将请求分配给业务线程池。对应 Netty 中的 workerGroup。

java.nio

这里简单介绍下 java.nio 对 Reactor 模式支持的几个概念Channel:socket 连接,文件连接等,用户数据传输,支持双向传输,Channel 可以将读取的网络数据写到 Buffer 中,也可以将 Buffer 数据发送到网络中。

Buffers: 存储数据,底层数组实现

Selectors:获取关注的 I/O 事件。每个 Channel 需要注册到 Selector 上,并标明关注的 I/O 事件,一个 Selector 可以同时注册多个 Channel。

SelectonKeys:保存的 I/O 事件和对应 Channel。

参考文章

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值