Reactor模式简要介绍

定义

反应器设计模式(Reactor pattern)是一种为处理并发服务请求,并将请求提交到一个或
者多个服务处理程序的事件设计模式。当客户端请求抵达后,服务处理程序使用多路分配策略,由一个非阻塞的线程来接收所有的请求,然后派发这些请求至相关的工作线程进行处理。
其中Wikipedia上说:“The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated request handlers.”。从这个描述中,我们知道Reactor模式首先是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handlers;这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。如果用图来表达:
在这里插入图片描述
从结构上,这有点类似生产者消费者模式,即有一个或多个生产者将事件放入一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事件来处理;而Reactor模式则并没有Queue来做缓冲,每当一个Event输入到Service Handler之后,该Service Handler会主动的根据不同的Event类型将其分发给对应的Request Handler来处理。

Reactor模式结构

在这里插入图片描述
Handle:即操作系统中的句柄,是对资源在操作系统层面上的一种抽象,它可以是打开的文件、一个连接(Socket)、Timer等。由于Reactor模式一般使用在网络编程中,因而这里一般指Socket Handle,即一个网络连接(Connection,在Java NIO中的Channel)。这个Channel注册到Synchronous Event Demultiplexer中,以监听Handle中发生的事件,对ServerSocketChannnel可以是CONNECT事件,对SocketChannel可以是READ、WRITE、CLOSE事件等。
Synchronous Event Demultiplexer:阻塞等待一系列的Handle中的事件到来,如果阻塞等待返回,即表示在返回的Handle中可以不阻塞的执行返回的事件类型。这个模块一般使用操作系统的select来实现。在Java NIO中用Selector来封装,当Selector.select()返回时,可以调用Selector的selectedKeys()方法获取Set,一个SelectionKey表达一个有事件发生的Channel以及该Channel上的事件类型。上图的“Synchronous Event Demultiplexer —notifies–> Handle”的流程如果是对的,那内部实现应该是select()方法在事件到来后会先设置Handle的状态,然后返回。不了解内部实现机制,因而保留原图。
Initiation Dispatcher:用于管理Event Handler,即EventHandler的容器,用以注册、移除EventHandler等;另外,它还作为Reactor模式的入口调用Synchronous Event Demultiplexer的select方法以阻塞等待事件返回,当阻塞等待返回时,根据事件发生的Handle将其分发给对应的Event Handler处理,即回调EventHandler中的handle_event()方法。
Event Handler:定义事件处理方法:handle_event(),以供InitiationDispatcher回调使用。
Concrete Event Handler:事件EventHandler接口,实现特定事件处理逻辑。

使用场景和易于理解的介绍

对于高并发系统,常会使用Reactor模式,其代替了常用的多线程处理方式,节省系统
的资源,提高系统的吞吐量。
下面用比较直观的形式来介绍这种模式的使用场景。
以餐厅为例,每一个人就餐就是一个事件,顾客会先看下菜单,然后点餐,处理这些就
餐事件需要服务人员。
就像一个网络服务会有很多的请求,服务器会收到每个请求,然后指派工作线程去处理
一样。
在多线程处理方式下:
一个人来就餐,一个服务员去服务,然后客人会看菜单,点菜。 服务员将菜单给后厨。
二个人来就餐,二个服务员去服务……
五个人来就餐,五个服务员去服务……
这类似多线程的处理方式,一个事件到来,就会有一个线程为其服务。
很显然这种方式在人少的情况下会有很好的用户体验,每个客人都感觉自己享有了最好
的服务。
如果这家餐厅一直这样同一时间最多来5个客人,这家餐厅是可以很好的服务下去的。
由于这家店的服务好,吃饭的人多了起来。
同一时间会来10个客人,老板很开心,但是只有5个服务员,这样就不能一对一服务
了,有些客人就不能马上享有服务员为其服务了。
老板为了挣钱,不得不又请了5个服务员。
现在又好了,每位顾客都享受最好最快的待遇了。
越来越多的人对这家餐厅满意,客源又多了,同时来吃饭的人到了20人,老板高兴但又
高兴不起来了,再请服务员吧,占地方不说,还要开工钱,再请人就挣不到到钱了。
怎么办呢?
老板想了想,10个服务员对付20个客人也是能对付过来的,服务员勤快点就好了,伺候
完一个客人马上伺候另外一个,还是来得及的。
综合考虑了一下,老板决定就使用10个服务人员的线程池!
但是这样又有一个比较严重的缺点:如果正在接受服务员服务的客人点菜很慢,其他的
客人可能就要等好长时间了。
有些脾气火爆的客人可能就等不了走人了。
这样,那就引入了Reactor模式。
那么,Reactor模式是如何处理这个问题呢?
老板后来发现,客人点菜比较慢,大部服务员都在等着客人点菜,其实干的活不是太
多。
老板之所以能当老板当然有点不一样的地方,终于发现了一个新的方法,那就是:当客
人点菜的时候,服务员就可以去招呼其他客人了,等客人点好了菜,直接招呼一声“服
务员”,马上就有个服务员过去服务。
在用了这个新方法后,老板进行了一次裁员,只留了一个服务员!
这就是用单个线程来做多线程的事。
实际的餐馆都是用的Reactor模式在服务。

猜你喜欢

转载自blog.csdn.net/u014303647/article/details/88820480