Java IOJava 杂谈

【译】reactor-siemens

2019-08-17  本文已影响1人  理查德成

原文地址: http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf

论文名称
Reactor
An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events

作者信息
Douglas C. Schmidt
schmidt@cs.wustl.edu
Department of Computer Science
Washington University, St. Louis, MO1

译者水平有限, 如有错误和疏漏, 欢迎指正

这篇论文的早期版本出现再书籍 “Pattern Languages of Program Design”(ISBN 0- 201-6073-4)中, 这本书由 Jim Coplien 和 Douglas C. Schmidt 编辑, 并由Addison-Wesley在1995年发布.

1. 意向

Reactor模式处理从一个或者多个客户端并发地发送来的服务请求. 应用中的每个服务由一些方法构成, 并且服务由负责分发特定于服务的请求独立事件处理器表示. 分发事件由一个 "启动调度器" 负责, 启动调度器管理注册的事件处理器. 分解服务请求由一个同步事件复用器负责.

2. 别称

Dispatcher(分发程序, 调度程序), Notifier(通知程序)

3. 示例

图1中为分布式日志服务设计的事件驱动服务说明了Reactor模式. 客户端程序使用日志服务来记录分布式环境下的状态信息. 状态信息一般包括 错误通知, debug跟踪信息以及性能报告. 日志记录发送到中央日志服务, 日志服务可以将日志信息记录到多种终端设备, 比如 控制台, 打印机, 文件或者网络数据库.

图1中的日志服务处理由客户端发送的日志记录和连接请求. 日志记录和连接请求可能通过多个句柄并发地发送到服务器. 句柄代表由操作系统管理的网络通信资源.

日志服务使用面向连接的协议与客户端通信, 如 TCP. 客户端必须向服务器发送连接请求, 之后才能记录日志. 服务器使用一个监听指定地址的句柄工厂等待客户端的请求连接, 监听的地址事先告知客户端. 当连接请求达到, 句柄工厂创建一个代表连接端点的新句柄, 从而建立客户端和服务的连接. 句柄返回给日志服务, 日志服务在返回的句柄上等待客户端请求的达到. 一旦客户端连接建立, 客户端可以并发地向服务发送日志记录请求. 日志服务通过连接上的socket句柄接收请求.

图1 分布式日志服务

开发一个并发地日志服务最直观的方式也许是使用多线程, 可以并发地处理多个客户端, 如图2所示. 这种方式同步地接收网络连接, 使用为每个连接分配一个线程的方式处理客户端日志记录请求.

图2多线程日志服务

但是, 使用多线程实现的日志服务不能解决以下问题:

由于这些缺点, 开发并发日志服务时, 多线程通常不是最有效的, 也不是最简洁的解决方案.

4. 上下文

分布式系统中从一个或多个客户端并发地接收事件的服务应用.

5. 问题

分布式系统中的服务应用必须处理发送请求的多个客户端. 然而在调用具体服务之前, 服务器应用必须多路分离以及分发每一个连接进来的请求到对应的服务提供者. 为了多路分离和分发客户端请求开发的高效服务机制需要解决以下问题:

6. 解决方案

将事件的同步多路复用程序, 和处理事件对应的事件处理器分发程序, 整合起来. 另外, 将特定于应用程序的调度和服务实现与通用事件解复用和调度机制解耦.

为应用提供的每个服务, 引入单独 Event Handler (事件处理器) 来处理特定类型的事件. 所有的Event Handler 实现同一个接口. 将Event Handler 注册到 Initiation Dispatcher(初始分发器), Initiation Dispatcher使用Synchronous Event Demultiplexer(同步事件多路复用器)等待事件的发生. 事件发生后, Synchronous Event Demultiplexer通知Initiation Dispatcher, Initiation Dispatcher同步地回调关联了事件的Event Handler. 然后Event Handler将事件处理分发给实现了请求的服务的方法.

7. 结构

Reactor模式主要的组成部件如下:

Handles

Synchronous Event Demultiplexer

Initiation Dispatcher

Event Handler

Concrete Event Handler

Reactor模式的部件结构如下OMT类图:

OMT class diagram

8. Dynamics

8.1 模块间的协作关系

Reactor模式中模块的协作关系如下:

下面的交互图说明了Reactor模式中应用代码和模块之间的协作关系:

sequence diagram
8.2 协作场景

日志服务中的Reactor模式协作场景有两部分。这两个场景展示了日志服务是如何使用响应式事件来分发来自多个客户端的句柄连接请求以及日志数据记录请求的。

8.2.1 客户端连接到响应式日志服务

第一个场景展示客户端连接到日志服务的步骤:

连接到日志服务步骤

步骤总结如下:

  1. 日志服务注册Logging Acceptor 到初始分发器来处理连接请求(1);
  2. 日志服务调用初始分发器的handle_events 方法(2);
  3. 初始分发器调用同步事件多路复用器的select 方法,等待连接请求或者日志数据的达到(3);
  4. 客户端连接到日志服务器(4);
  5. 初始分发器通知Logging Acceptor 有新连接达到(5);
  6. Logging Acceptor 接受新连接(6);
  7. Logging Acceptor 创建一个Logging Handler 来为新客户端服务(7);
  8. Logging Handler 将它的socket句柄注册到初始分发器,并且要求,当socket可读时,初始分发器通知它(8);
8.2.2 客户端发送日志记录请求到响应式日志服务

第二个场景展示响应式日志服务处理日志记录请求的步骤:

日志服务处理请求步骤

步骤总结如下:

  1. 客户端发送日志记录请求(1);
  2. 当客户端日志记录请求在socket上列队时,初始分发器通知关联的Logging Handler(2);
  3. 以非阻塞的方式接收日志记录(重复步骤2和3直到日志记录被完全接收);
  4. Logging Handler 处理日志记录并写到标准输出(4);
  5. Logging Handler 返回到初始分发器的事件循环(5)。

自此reactor模式该篇论文对reactor模式的核心已经翻译完毕,后面关于C++实现reactor模式,使用reactor的框架,以及reactor模式的优缺点不想翻译 哈哈哈

上一篇 下一篇

猜你喜欢

热点阅读