Reactor模式详解

  • 时间:
  • 浏览:1
  • 来源:大发快3APP下载—大发时时彩登录地址

Provides coarse-grained concurrency control: The Reactor pattern serializes the invocation of event handlers at the level of event demultiplexing and dispatching within a process or thread. Serialization at the Initiation Dispatcher level often eliminates the need for more complicated synchronization or locking within an application process.

原文链接:[http://wely.iteye.com/blog/2329842]

Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events中,经常以Logging Server来分析Reactor模式,你這個 Logging Server的实现完整性遵循这里对Reactor描述,因而插进这里以做参考。Logging Server中的Reactor模式实现分有有有好几个 每段:Client连接到Logging Server和Client向Logging Server写Log。因而对它的描述分成这有有有好几个 步骤。

Client连接到Logging Server

Improve modularity, reusability, and configurability of event-driven applications: The pattern decouples application functionality into separate classes. For instance, there are two separate classes in the logging server: one for establishing connections and another for receiving and processing logging records. This decoupling enables the reuse of the connection establishment class for different types of connection-oriented services (such as file transfer, remote login, and video-on-demand). Therefore, modifying or extending the functionality of the logging server only affects the implementation of the logging handler class.

对于性能,它我我觉得怎么会让第或多或少关于Efficiency的描述,即应用线程池池的切换、同步、数据的移动会引起性能难题。也怎么会让说从性能的深层上,它最大的提升怎么会让减少了性能的使用,即只能每个Client对应有有有好几个 应用线程池池。我的理解,或多或少业务逻辑处理所以有之前 也会用到相同的应用线程池池,IO读写操作相对CPU的操作还是要慢所以有,即使Reactor机制中每次读写可能性能保证非阻塞读写,这还上都能能减少或多或少应用线程池池的使用,怎么会让这减少的应用线程池池使用对性能有没办法 大的影响吗?答案貌似是肯定的,这篇论文(SEDA: Staged Event-Driven Architecture - An Architecture for Well-Conditioned, Scalable Internet Service)对随着应用线程池池的增长带来性能降低做了有有有好几个 统计:

在你這個 统计中,每个应用线程池池从磁盘中读8KB数据,每个应用线程池池读同有有有好几个 文件,因而数据一种是缓指在操作系统内控 的,即减少IO的影响;所有应用线程池池是之前 分配的,不用有应用线程池池启动的影响;所有任务在测试内控 产生,因而不用有网络的影响。该统计数据运行环境:Linux 2.2.14,2GB内存,4-way 60 0MHz Pentium III。从图中还都能能看出,随着应用线程池池的增长,吞吐量在应用线程池池数为8个左右的之前 开使英文线性下降,怎么会让到6有有有好几个 之前 而飞快下降,其相应事件也在应用线程池池达到256个后指数上升。即1+1<2,可能性应用线程池池切换、同步、数据移动会有性能损失,应用线程池池数增加到一定数量时,你這個 性能影响效果会更加明显。对于这点,还还都能能参考C10K Problem,用以描述一并有10K个Client发起连接的难题,到2010年的之前 可能性跳出10M Problem了。当然都是人说:Threads are expensive are no longer valid.在不久的将来可能性又会指在不同的变化,可能性你這個 变化正在、可能性指在着?没办法 做过比较仔细的测试,因而不敢随便断言那此,然而另一方观点,即使应用线程池池变的影响并没办法 之前 没办法 大,使用Reactor模式,甚至时SEDA模式来减少应用线程池池的使用,加上上或多或少解耦、模块化、提升复用性等优点,还是值得使用的。

Reactor Pattern WikiPedia

Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous EventsScalable IO In JavaC10K Problem WikiPedia

Efficiency: Threading may lead to poor performance due to context switching, synchronization, and data movement [2];

对EventHandler的定义有一种设计思路:single-method设计和multi-method设计:

A single-method interface:它将Event封装成有有有好几个 Event Object,EventHandler只定义有有有好几个 handle_event(Event event)最好的土辦法 。你這個 设计的好处是促进扩展,可之前 来方便的加上新的Event类型,然而在子类的实现中,还都能能判断不同的Event类型而再次扩展成 不同的处理最好的土辦法 ,从你這個 深层上来说,它又不促进扩展。另外在Netty3的使用过程中,可能性它不停的创建ChannelEvent类,因而会引起GC的不稳定。A multi-method interface:你這個 设计是将不同的Event类型在 EventHandler中定义相应的最好的土辦法 。你這個 设计怎么会让Netty4中使用的策略,其蕴藏高有好几个 目的是处理ChannelEvent创建引起的GC不稳定, 另外有有有好几个 好处是它还都能能处理在EventHandler实现时判断不同的Event类型而有不同的实现,然而你這個 设计会给扩展新的Event类型时带来非常 大的麻烦,可能性它还都能能该接口。关于Netty4对Netty3的改进还都能能参考这里

4.0 removes event object creation almost completely by replacing the event objects with strongly typed method invocations. 3.x had catch-all event handler methods such as handleUpstream() and handleDownstream(), but this is not the case anymore. Every event type has its own handler method now:

Reactor模式的缺点貌似也是显而易见的:

1. 相比传统的简单模型,Reactor增加了一定的僵化 性,因而有一定的门槛,怎么会让不易于调试。2. Reactor模式还都能能底层的Synchronous Event Demultiplexer支持,比如Java中的Selector支持,操作系统的select系统调用支持,可能性要另一方实现Synchronous Event Demultiplexer可能性不用有没办法 高效。3. Reactor模式在IO读写数据时还是在同有有有好几个 应用线程池池中实现的,即使使用多个Reactor机制的具体情况下,那此共享有有有好几个 Reactor的Channel可能性跳出有有有好几个 长时间的数据读写,会影响你這個 Reactor中或多或少Channel的相应时间,比如在大文件传输时,IO操作就会影响或多或少Client的相应时间,因而对你這個 操作,使用传统的Thread-Per-Connection或许是有有有好几个 更好的确定,或则此时使用Proactor模式。

在Java的NIO中,对Reactor模式是是否缝的支持,即使用Selector类封装了操作系统提供的Synchronous Event Demultiplexer功能。你這個 Doug Lea可能性在Scalable IO In Java蕴藏非常深入的解释了,因而不再赘述,另外这篇文章对Doug Lea的Scalable IO In Java有或多或少简单解释,至少它的代码格式比Doug Lea的PPT要整洁或多或少。

还都能能指出的是,不同这里使用InitiationDispatcher来管理EventHandler,在Doug Lea的版本中使用SelectionKey中的Attachment来存储对应的EventHandler,因而只能注册EventHandler你這個 步骤,可能性设置Attachment怎么会让这里的注册。怎么会让在这篇文章中,Doug Lea从单应用线程池池的Reactor、Acceptor、Handler实现你這個 模式出发;演化为将Handler中的处理逻辑多应用线程池池化,实现同类Proactor模式,此时所有的IO操作还是单应用线程池池的,因而再演化出有有有好几个 Main Reactor来处理CONNECT事件(Acceptor),而多个Sub Reactor来处理READ、WRITE等事件(Handler),那此Sub Reactor还都能能分别再另一方的应用线程池池中执行,从而IO操作也多应用线程池池化。你這個 最后有有有好几个 模型正是Netty中使用的模型。怎么会让在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events的9.5 Determine the Number of Initiation Dispatchers in an Application中都是相应的描述。

Improves application portability: The Initiation Dispatcher’s interface can be reused independently of the OS system calls that perform event demultiplexing. These system calls detect and report the occurrence of one or more events that may occur simultaneously on multiple sources of events. Common sources of events may in- clude I/O handles, timers, and synchronization objects. On UNIX platforms, the event demultiplexing system calls are called select and poll [1]. In the Win32 API [16], theWaitForMultipleObjects system call performs event demultiplexing.

1. Logging Server注册LoggingAcceptor到InitiationDispatcher。2. Logging Server调用InitiationDispatcher的handle_events()最好的土辦法 启动。3. InitiationDispatcher内控 调用select()最好的土辦法 (Synchronous Event Demultiplexer),阻塞停留Client连接。4. Client连接到Logging Server。5. InitiationDisptcher中的select()最好的土辦法 返回,并通知LoggingAcceptor有新的连接到来。 6. LoggingAcceptor调用accept最好的土辦法 accept你這個 新连接。7. LoggingAcceptor创建新的LoggingHandler。8. 新的LoggingHandler注册到InitiationDispatcher中(一并也注册到Synchonous Event Demultiplexer中),停留Client发起写log请求。Client向Logging Server写Log

归功与Netty和Java NIO对Reactor的宣传,本文慕名而学习的Reactor模式,因而可能性默认Reactor具有非常优秀的性能,然而慕名归慕名,到这里,我还是要不得不问另一方Reactor模式的好指在哪里?即为那此要使用你這個 Reactor模式?在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events中是没办法 说的:

1. Client发送log到Logging server。2. InitiationDispatcher监测到相应的Handle蕴藏事件指在,返回阻塞停留,根据返回的Handle找到LoggingHandler,并回调LoggingHandler中的handle_event()最好的土辦法 。3. LoggingHandler中的handle_event()最好的土辦法 中读取Handle中的log信息。4. 将接收到的log写入到日志文件、数据库等设备中。3.4步骤循环直到当前日志处理完成。5. 返回到InitiationDispatcher停留下一次日志写请求。Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events有对Reactor模式的C++的实现版本,多年不用C++,因而略过。 

简单描述一下Reactor各个模块之间的交互流程,先从序列图开使英文:

1. 初始化InitiationDispatcher,并初始化有有有好几个 Handle到EventHandler的Map。2. 注册EventHandler到InitiationDispatcher中,每个EventHandler蕴藏对相应Handle的引用,从而建立Handle到EventHandler的映射(Map)。3. 调用InitiationDispatcher的handle_events()最好的土辦法 以启动Event Loop。在Event Loop中,调用select()最好的土辦法 (Synchronous Event Demultiplexer)阻塞停留Event指在。4. 当某个或或多或少Handle的Event指在后,select()最好的土辦法 返回,InitiationDispatcher根据返回的Handle找到注册的EventHandler,并回调该EventHandler的handle_events()最好的土辦法 。5. 在EventHandler的handle_events()最好的土辦法 中还还都能能向InitiationDispatcher中注册新的Eventhandler,比如对AcceptorEventHandler来,当有新的client连接时,它会产生新的EventHandler以处理新的连接,并注册到InitiationDispatcher中。

Separation of concerns: The Reactor pattern decouples application-independent demultiplexing and dispatching mechanisms from application-specific hook method functionality. The application-independent mechanisms become reusable components that know how to demultiplex events and dispatch the appropriate hook methods defined by Event Handlers. In contrast, the application-specific functionality in a hook method knows how to perform a particular type of service.

在处理了那此是Reactor模式后,另一所有人来看看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>,有有有好几个 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接口,实现特定事件处理逻辑。

要回答你這個 难题,首先当然是求助Google或Wikipedia,其中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 An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events)上说:“The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients. Each service in an application may consistent of several methods and is represented by a separate event handler that is responsible for dispatching service-specific requests. Dispatching of event handlers is performed by an initiation dispatcher, which manages the registered event handlers. Demultiplexing of service requests is performed by a synchronous event demultiplexer. Also known as Dispatcher, Notifier”。这段描述和Wikipedia上的描述同类,有多个输入源,有多个不同的EventHandler(RequestHandler)来处理不同的请求,Initiation Dispatcher用于管理EventHander,EventHandler首没办法 注册到Initiation Dispatcher中,怎么会让Initiation Dispatcher根据输入的Event采集给注册的EventHandler;然而Initiation Dispatcher不用监听Event的到来,你這個 工作交给Synchronous Event Demultiplexer来处理。

Programming simplicity: Threading may require complex concurrency control schemes;

那此貌似是所以有模式的共性:解耦、提升复用性、模块化、可移植性、事件驱动、细力度的并发控制等,因而不用能很好的说明那此,有点痛 是它鼓吹的对性能的提升,这里并没办法 体现出来。当然在这篇文章的开头有描述过另一种直观的实现:Thread-Per-Connection,即传统的实现,提到了你這個 传统实现的以下难题:

第一次听到Reactor模式是三年前的某个晚上,有有有好几个 室友经常跑过来问我那此是Reactor模式?我上网查了一下,所以另一所有人都是给出NIO中的 Selector的例子,怎么会让怎么会让NIO里Selector多路复用模型,怎么会让给它起了有有有好几个 比较fancy的名字而已,我我觉得它引入了EventLoop概 念,这对我来说是新的概念,怎么会让代码实现却是一样的,因而我并没办法 很在意你這個 模式。然而最近开使英文读Netty源码,而Reactor模式是所以有介绍Netty的文章中被大肆宣传的模式,因而我再次问另一方,那此是Reactor模式?本文怎么会让对你這個 难题关于我的或多或少理解和尝试着来解答。