微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

reactor模式与java nio


Reactor是由Schmidt,Douglas C提出的一种模式,在高并发服务器实现中广泛采用。改模式采用事件驱动方式,当事件出现时,后调用相应的事件处理代码(Event Handler)。

这个模式是高并发服务器的基础,如Nginx和lighttpd。这两种对大并发,但每个请求处理都很快的场景非常适合。通常的web访问就是这个特点。

结构
包括了5个部分,其中handle和Synchronous Event Demultiplexer有OS实现。
Handles:
就是网络连接(connection),每个网络连接都由一个handle表示。

Event(事件)
ACCEPT_EVENT:表示收到连接请求
READ_EVENT:表示收到数据
WRITE_EVENT:表示socket可以足够的缓冲区,可以向其写入数据。
TIMEOUT_EVENT:超时。Java NIO不支持这个事件。
SIGNAL_EVENT:信号。Java NIO不支持这个事件。
CLOSE_EVENT:该socket被关闭。Java NIO不支持这个事件。

Event Handler
事件处理代码,该对象实例(instance)是和handle关联的。每个Event Handler处理一个handle上的事件。一般的服务器中至少有两种事件处理代码一个是用来接收连接请求(accept event handler),响应ACCEPT_EVENT。,一个用来处理接受的请求(connection event handler),响应READ_EVENT和WRITE_EVENT。

Synchronous Event Demultiplexer(事件多路分离系统)
该模式的核心,等待handles上的事件。没有事件出现时,一直阻塞(blocking);当某个(某些)handles上有时间产生时,返回。这个是实现一般由操作系统提供,如linux的select、poll及epoll等。

Initiation dispatcher
该对象负责管理Event Handlers(增加删除等),当某个handle上有事件出现时,调用相应的
内部使用Synchronous Event Demultiplexer

reactor的论文中给出了实例代码
Logging_Acceptor是处理接收请求的event handler。
Logging_Handler是处理实际请求的event handler
Initiation_dispatcher::instance是单利模式的Initiation dispatcher

线程模型
论文中使用的是单线程模型,即一个线程同时处理接受请求和处理请求。该模型中,如果每个请求的处理时间较长,则会影响真个系统的吞吐率。

更为普遍的是使用多线程模型。多线程的基本方式是1:n。
1个线程用来接受连接请求,执行accept event handler。
其他的线程用来处理连接请求,执行connection event handler。n的数量可以根据运行情况动态调整。如果每个连接的处理非常快,可能一个线程就够了;如果处理的时间很长,则可能一个连接就要有一个线程。

java NIO
java nio就是依照reactor模式设计的。java nio中的主要抽象:
Selector:相当于Synchronous Event Demultiplexer
SelectionKey: 相当于event,和一个SocketChannel关联
SocketChannel:相当于handle
java nio中没有提供initial dispatcher的抽象,这部分功能需要用户自行实现。
java nio中没有提供event handler的抽象,这部分功能需要用户自行实现。

netty
作为API,java nio不会设计的很全面,只会提供基本的功能。对一般的用户来说,java nio提供的编程界面还是比较原始(pirmitive),不是很容易使用。netty是一个网络编程框架,在java nio的基础上提供了更高层的抽象。netty的编程比起nio有极大的简化。netty中提供了reactor的所有封装,用户在使用中只需实现event handler即可。

netty在event handler上又提供了一层抽象,ChannelPipeline和ChannelHandler。
ChannelPipeline类似于原来的event handler,用来处理连接请求。ChannelPipeline由若干个ChannelHandler构成,ChannelPipeline会分别调用这些ChannelHandler来处理连接请求。这种设计类似于servlet中的filter chain。所有的ChannelHandler和在一起,形成了处理链路。

netty同样提供了对线程模型的支持,具体可以参考netty的文档。

proactor和reactor的区别
主要区别是在处理连接请求时的方式:
reactor: 收到事件后,同步处理。该请求没有完成后,该线程不会再去处理其他请求。
proactor:收到事件,异步处理。该请求会执行异步调用(如异步读写文件等),然后该请求调用返回,该线程会继续执行其他的请求。但是第一个请求并没有处理完毕,当异步操作完成时,后有时间通知到第一个请求,完成处理。proactor的编程会比较复杂。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...