Java-技术专区-设计模式-reactor模式
模型:
反应器模式做法是:汽车是乘客访问的主体(Reactor),乘客上车后,到售票员(acceptor)处登记,之后乘客便可以休息睡觉去了,当到达乘客所要到达的目的地后,售票员将其唤醒即可。
反应器模式与观察者模式在某些方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联。
JDK中模式原型复现:
NIO有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,接着我们可以处理这些数据。
首先,仅仅是建立连接(socket),就占用了服务器的线程资源。如果客户端还没有发出相应的数据请求,那么服务器就要一直等待他们的数据流过来,然后再进行读取,如此往复 … … 一直都blocking。服务器处在一个高负荷状态中。
NIO出来之后,进入改革开放时期,有了这么几个角色,ServerSocketChannel,SelectionKey,Selector。
这几个角色都是做什么用的呢?需要了解一下reactor模式(反应堆模式)。作为服务端,如果什么操作都要依赖于客户端,很多操作都阻塞,如上面的代码片段所示。reactor模式提供了一种很好的事件处理机制,以分离事件处理对象与事件之间的耦合。如下图示(详细请看参考资料(1)):
说明:
Acceptor就是我们Server端的主要任务消化者;
Initiation Dispatcher是事件(Event)的分发者;
HTTP Handler是具体操作人。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
首先,在Initiation Dispatcher中注册一个acceptor
(1:register Acceptor),这个Acceptor是跟事件绑定的,它仅仅关心某种事件(event)。Initiation Dispatcher不断地循环获取请求过来的事件
(2:handle events),如果发现有对应Acceptor关心的事件
(3:connect),通知Acceptor有事件发生
(4:new connection)。 Acceptor针对此事件进行处理,创建了新的HTTP Handler
(5:create handler))一轮事件获取和分发完成。
那么handler是不是就抓住这个connection不放,然后一直苦苦等待数据流的到来呢?
不是的,它也是将自己和自己关心的事件注册到Initiation Dispatcher。如果Initiation Dispatcher在handle Events时发现了它关心的事件,那么就会交由它去进行相应处理。如下图示,在连接完成后,browser提交的get请求,handler的处理过程:
这里面尤其要注意到,2:read ready,之后才read request,也就是说,handler在dispatcher中注册了自己关心的事件(READ),然后在写的时候,也是类似情况。
以上的过程就实现了非阻塞的处理方式,客户端的连接可以非阻塞(这是意思是,acceptor不必一直苦苦等候),然后对客户端过来的request内容,也是非阻塞(这里是不必苦苦等待其数据的到来),都是不必一直眼巴巴的看着那个连接,那些数据,而是如果有我关心的事件了,我再进行处理,期间完全相信Initiation Dispatcher就行了。
这里有一点要注意,就是现在的reactor模式都是建立在操作系统的基础上实现的,不同的操作系统有不同的实现方式。而且都不支持多线程(针对Initiation Dispatcher而言)。
相关文章
- 接口测试第7讲:使用HttpRunner完成半手工接口测试
- 软件测试|黑盒测试方法论-判定表
- laravel中 URL 不做 CSRF 安全校验的两种方法
- 接口测试第8讲:基于unittest框架requests自动化测试上
- laravel 中数据验证
- 接口测试第9讲:基于unittest框架requests自动化测试下
- 接口测试第10讲:基pytest框架requests自动化测试
- 请求接口时出现 Status (blocked:other)
- Laravel 批量更新
- Laravel orWhere条件
- Mac iTerm ssh 连接服务器
- crontab 脚本测试demo
- Nginx 查看接口请求内容
- 记录一次 laravel 项目队列拥堵的问题
- kafka 入门
- 使用 supervisor 来管理 kafka进程
- Failed to get D-Bus connection: Operation not permitted
- laravel 中使用 Hash::make() 对用户密码进行加密
- 并发情况下产品超卖
- laravel 中字段格式处理