ACE应用-第1章 应用模式语言开发应用级网关
发布: 2008-6-13 13:48 | 作者: Douglas C. Schmidt | 来源: 转载 | 查看: 225次
意图:接受器-连接器模式使网络系统中的连接建立及服务初始化与服务处理去耦合。
动机和压力:面向连接的应用(比如我们的应用级网关)和中间件(比如CORBA)常常使用像scoket[13]这样的较低级的网络编程接口来编写。以下需求所带来的压力影响了使用这些较低级接口编写的服务的初始化:
1. 将连接建立代码复用于每个新服务。服务的关键特性,比如通信协议或数据格式,应该能够独立于用于建立连接的机制而透明地发展。因为服务特性的变动比连接建立机制更为频繁,分离这些事务有助于降低软件的耦合、并增加代码复用。
2. 使连接建立代码可跨越含有不同网络编程接口的平台而移植。为接受连接和执行服务而对接受器-连接器的机制进行参数化有助于通过整个地替换这些机制来改善可移植性。这使得连接建立代码可跨越含有不同网络编程接口的平台进行移植,比如有Socket、但没有TLI,或者反之亦然。
3. 使用灵活的服务并发策略。在连接建立后,对端应用使用此连接来交换数据,以执行某种类型的服务,比如远地登录或HTML文档传输。服务可以运行在单线程中、在多线程中,或多进程中,而不管连接是如何建立的,或如何被初始化的。
4. 确保被动模式的I/O句柄不会被偶然用于读写数据。通过彻底使连接建立逻辑与服务处理逻辑去耦合,被动模式的Socket端点不可能被不正确地使用(例如,试图在用于接受连接的被动模式侦听者端口上读写数据)。这消除了一类重要的网络编程错误。
5. 高效地主动与大量对端建立连接。当应用必须在长延迟WAN上与大量对端高效地建立连接时,可能必须使用异步操作,并在非阻塞模式中发起和完成多个连接。
解决方案:应用接受器-连接器模式来使网络应用中的对端服务的连接及初始化与在它们被连接和初始化后所执行的服务处理去耦合。
结构、参与者和实现:图1-11演示接受器-连接器模式中的参与者的分层结构。Acceptor和Connector组件是对连接和启用Svc Handler所需的资源进行装配的工厂。Svc Handler是与相连对端交换消息的组件。

图1-11 接受器-连接器模式中的结构和参与者
接受器-连接器的连接层中的参与者有效地利用了反应堆模式。例如,在Reactor通知Connector、一个先前发起的连接到对端的请求已经完成后,Connector的异步初始化策略就会建立起一个连接。反应堆模式的使用使得多个Svc Handler能在单线程控制中被异步地初始化。
为增加灵活性,Acceptor和Connector组件可通过特定类型的IPC机制和SVC HANDLER来参数化。IPC机制提供底层传输机制(比如Socket或TLI的C++包装外观)来用于建立连接;而SVC HANDLER定义的抽象接口用于定义与相连对端进行通信的服务。Svc Handler可通过PEER STREAM端点来参数化。当连接建立时,Acceptor和Connector组件将此端点与它的对端关联起来。
通过从Event Handler继承,Svc Handler可以登记到Reactor,并使用反应堆模式来在与Acceptor或Connector相同的线程控制中处理它的I/O事件。反过来,Svc Handler也可以使用主动对象模式,在单独的线程中处理它的I/O事件。1.3.7评估了在这两种模式之间进行的折衷。
参数化类型被用于使接受器-连接器模式的连接建立策略与服务类型及连接机制类型去耦合。开发者为这些类型提供模板参数,以生成应用层Acceptor或Connector,比如由网关用于初始化Supplier和Consumer Handler的Connector。这样的设计使得开发者可以整个地替换SVC HANDLER和IPC机制,而不会影响接受器-连接器模式的初始化策略。
注意通过使用[2]中描述的抽象工厂(Abstract Factory)或工厂方法(Factory Method)模式,经由继承和动态绑定可以达到类似程度的去耦合。之所以使用参数化类型来实现此模式,是因为它们改善了运行时效率。一般而言,模板为改善运行时性能而在编译及链接时开销与空间开销之间进行折衷。

图1-12 Acceptor组件的动力特性
动力特性:图1-12演示该模式的Acceptor组件的参与者之间的动力特性。这些动力特性被划分进以下三个阶段:
1. 端点初始化阶段,创建由PEER ACCEPTOR封装的被动模式端点,这个PEER ACCEPTOR被绑定到一个网络地址,比如IP地址和端口号。该被动模式端点侦听来自对端的连接请求。它被登记到Reactor,后者驱动事件循环,在该端点上等待连接请求从对端到达。
2. 服务启用阶段。因为Acceptor继承自Event Handler,当连接请求事件到达时,Reactor可以分派Acceptor的handle_event方法。该方法执行Acceptor的Svc Handler初始化策略:(1)装配创建新Concrete Svc Handler对象所需的资源,(2)将连接接受进该对象,以及(3)通过调用Svc Handler的open挂钩方法将其启用。
3. 服务处理阶段。在Svc Handler被启用后,它处理在PEER STREAM上到来的事件消息。Svc Handler可以使用像反应堆或主动对象[1]这样的模式来处理到来的事件消息。
在该模式的Connector组件的参与者之间的动力特性可被划分进下面三个阶段:
1. 连接发起阶段,主动地连接一或多个Svc Handler到它们的对端。连接可被同步或异步地发起。Connector的connect方法实现主动建立连接的策略。
2. 服务初始化阶段,当Svc Handler的连接成功完成时,通过调用它的open方法来将其启用。Svc Handler的open方法随即执行服务特有的初始化。
3. 服务处理阶段,使用在Svc Handler和与其相连的对端之间交换的数据来执行应用特有的服务处理。
图1-13使用异步连接建立来演示动力特性的这三个阶段。注意Connector的连接发起阶段是怎样暂时与服务初始化阶段分离的。这样的设计使得多个连接发起可在单线程控制中并行地进行。同步连接建立的动力特性也是类似的。在此例中,Connector将连接发起和服务初始化阶段组合进单个阻塞操作中。

图1-13 异步Connector组件的动力特性
一般而言,同步的连接建立对于以下情况来说是有用的:
-如果建立连接的响应延迟非常低,比如通过回路(loopback)设备与在同一主机上的服务器建立连接。
-如果有多个线程控制可用,并且,使用不同线程来同步地连接每个Svc Handler是可行的。
-如果不到连接已建立,客户应用无法执行有用的工作。
相反,异步的连接建立对于以下情况来说是有用的:
-如果连接响应延迟很高,而又有许多对端要连接,例如,在高响应延迟的WAN上建立大量连接。
-如果只有单个线程控制可用,例如,如果OS平台不提供应用级线程。
-如果客户应用必须在连接正在被建立的同时执行另外的工作,比如刷新GUI。
情况常常是,网络服务(比如我们的应用级网关)必须在不知道它们将同步还是异步地进行连接的情况下开发。因此,一个通用网络编程构架所提供的组件必须支持多种同步和异步的使用情况。
接受器-连接器模式通过使连接建立逻辑与服务处理逻辑相分离,增加了网络构架组件的灵活性和复用。在(1)Acceptor及Connector组件与(2)Svc Handler之间的唯一耦合发生在服务初始化阶段,在Svc Handler的open方法被调用时。在这时,Svc Handler可以使用任何合适的应用级协议或并发策略来执行它的服务特有的处理。
例如,当消息到达网关时,Reactor可用于分派Supplier Handler,以划分消息帧、确定外发路由,并递送消息给它们的Consumer Handler。但是,Consumer Handler可以使用不同类型的并发机制(比如1.3.7描述的主动对象)来发送数据给远地的目的地。
使用:图1-14演示接受器-连接器模式的Acceptor组件是怎样在网关扮演被动连接角色时被使用的。在此例中,对端连接到网关,后者使用Acceptor来使Supplier和Consumer Handler的被动初始化与处理器被初始化后所执行的路由任务去耦合。

图1-14 在网关中使用Acceptor组件
图1-15演示接受器-连接器模式的Connector组件怎样被网关用于简化连接大量对端的任务。在此例中,对端地址在网关初始化的过程中从配置文件中读取。网关使用构建器(Builder)模式[2]来将这些地址绑定到动态分配的Consumer Handler或Supplier Handler。因为这些处理器继承自Svc Handler,可以使用迭代器模式[2]来异步地发起所有连接。随后就使用Connector来并行地完成连接。

图1-15 在网关中使用Connector组件
图1-15显示Connector在四个连接被建立后的状态。其他三个还未完成的连接由Connetor拥有。如该图中所示,Connector维护连接还暂未完成的三个Handler的表。在连接完成时,Connector将每个已连接的Channel从它的表中移除,并将其启用。在单线程实现中,Supplier Handler在它们被启用后将自身登记到Reactor。自此时起,当路由消息到达时,Supplier Handler接收它们、并转发给Consumer Handler,后者再将这些消息递送到它们的目的地(这些活动在1.3.6中描述)。
除了建立连接,网关还可与Connector和Reactor联合使用、以确保连接在网络错误发生时重启。通过确保信道在意外断开时(例如,如果对端崩溃,或由于网络拥塞、大量的数据在Consumer Handler处排队等待)自动地重新发起,增强了网关的容错性。如果连接意外失败,通过使用Reactor的定时器分派能力,一种指数后退算法可以高效地重启连接。
在像inentd[13]和listen[14]这样的网络服务器管理工具中,可以发现接受器-连接器模式的意图和综合体系结构。这些工具利用主接受器进程,在一组通信端口上侦听连接。每个端口被关联到一个与通信有关的服务(比如标准的Internet服务ftp、telnet、daytime和echo)。当服务请求到达被监控的端口时,接受器进程接受该请求,并分派适当的预登记处理器来执行服务。
