贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

ACE技术论文集-第7章 ACE反应堆Reactor的设计和使用

发布: 2008-6-13 14:43 | 作者: Prashant Jain and D | 来源: 转载 | 查看: 514次

7.3.2 平台相关的类组件
 
ACE_Reactor类是应用用以访问ACE反应堆构架的公共接口。ACE_Reactor接口由一些虚方法组成。因此,它可以通过继承来扩展。
但是,扩展ACE_Reactor最常用的方法并不是派生它的子类。相反,如图7-6所示,桥接模式[6]被用来使ACE_Reactor接口与它的ACE_Reactor_Impl子类实现去耦合。ACE构架提供的两个子类包括ACE_Select_Reactor和ACE_WMFO_Reactor,它们分别封装了select和WaitForMultipleObjects OS事件多路分离调用。
在不同OS平台上,ACE_Reactor_Impl子类的实现也不同。但是,ACE_Reactor接口提供的方法的名字和总的功能保持不变。这种统一性源于ACE_Reactor的设计的模块性,该设计还增强了反应堆的复用、可移植性和可维护性。ACE_Reactor的WaitForMultipleObjects和select版本概述如下。
 
7.3.2.1 ACE_Select_Reactor
 
如图7-6(1)所示,基于select的ACE_Reactor包含有三个ACE_Event_Handler * 数组。这些数组存储的指针指向已登记用来处理各种类型事件的具体事件处理器。
ACE_Handle_Set类为底层的fd_set位掩码数据类型提供高效的C++包装。fd_set将I/O句柄名字空间映射到紧凑的位向量表示,并提供若干操作来置位、复位和测试与I/O句柄相对应的位。可传给select调用一或多个fd_set。
ACE_Handle_Set类通过以下方法来优化若干常用的fd_set操作:(1)使用“全字”(full-word)比较,以使不必要的位操作最少化, (2)缓存某些值,以避免每次调用都计算位偏移,以及(3)使用一种异或算法,它与fd_set中的活动句柄的数目、而非潜在的活动句柄的数目线性相关。
 
7.3.2.2 ACE_WMFO_Reactor
 
WaitForMultipleObjects接口比select更为通用,它允许应用等待更广泛的事件,比如同步事件。因此,基于WaitForMultipleObjects的ACE_Reactor既不需要三个ACE_Event_Handler * 数组,也不需要ACE_Handle_Set类,而是在内部分配和使用单个的ACE_Event_Handler指针数组和句柄数组,以存储已登记的具体事件处理器。
 
 
图7-6 将桥接模式用于反应堆实现
7.4 分布式日志服务例子
 
反应堆构架意在简化事件驱动应用的开发,比如Web服务器[13, 14]和CORBA对象请求代理[15]。这一部分描述一个分布式日志服务(distributed logging service)的设计和实现,以演示ACE_Reactor在实践中的应用。
 
7.4.1 综述
 
日志提供一种“只追加”的存储服务,记录由一或多个应用发来的诊断信息。日志的主要单元是记录。到来的记录被追加到日志的末尾,而所有其它类型的写访问都是被禁止的。
如图7-7所示,下面检查的日志服务使用客户/服务器体系结构,以使通过TCP/IP网络连接的工作站和服务器能够记录事件。日志服务将ACE_Reactor的多路分离与分派特性和[16]中描述的C++ IPC包装库提供的BSD sockets与系统V传输层接口(TLI)的OO接口结合在了一起。
 
 
图7-7 分布式日志服务中的组件
 
日志服务中的关键组件描述如下:
 
应用日志接口(Application logging interface):在客户主机上运行的应用进程,例如,P1、P2、P3,使用ACE_Log_Msg C++类来生成日志记录,比如LM_ERROR和LM_DEBUG。ACE_Log_Msg::log方法提供一种printf风格的接口。图7-8概述了在应用接口、客户和服务器日志看守之间交换的记录的若干优先级和数据格式。当被应用调用时,日志接口格式化日志记录,打上时间戳,将它们写到周知的STREAM管道[17]中去。如下所述,客户日志看守负责处理这些记录。
 
// The following enum indicates the relative
// priorities of the logging messages.
enum Log_Priority
{
// Messages that contain information normally
// used only when debugging a program.
LM_DEBUG,
 
// Critical conditions, e.g., hard device errors
LM_ERROR
 
// ...
};
 
struct Log_Record
{
enum {
// Maximum number of bytes in logging record.
MAXLOGMSGLEN = 1024
};
 
// Type of logging record.
Log_Priority type_;
 
// length of the logging record.
long length_;
 
// Time logging record generated.
long time_stamp_;
 
// Id of process that generated the record.
long pid_;
 
// Logging record data.
char rec_data_[MAXLOGMSGLEN];
};
图7-8 日志记录格式
 
客户日志看守(Client logging daemon):客户日志看守运行在所有参与分布式日志服务的主机上。每个客户日志看守与STREAM管道的读端相连,后者用于从这台机器上的应用那里接收日志记录。使用STREAM管道是因为它们是只用于本地主机的IPC的高效形式。此外,STREAM管道的语义允许“结合优先级”的消息,可按照“重要性顺序”,以及“到达顺序”接收[18]。
客户日志看守从应用进程那里持续地接收日志记录。它随后将多字节的记录头字段转换为网络字节顺序。最后,它使用TCP将记录转发给服务器日志看守。服务器通常运行在远地主机上。
 
服务器日志看守(Server logging daemon):服务器日志看守持续地收集、重格式化和输出到来的日志记录。这一部分的余下部分专注于服务器日志看守。在此例中演示和描述了多种ACE_Reactor和ACE C++ socket包装机制。
 
7.4.2 服务器日志看守
 
下面描述用来构造服务器日志看守的类的接口和实现。日志服务器在单独的进程中运行,并发地处理来自客户的日志记录。并发是由ACE_Reactor提供的,它将它的注意力以循环方式“分时”给每个活动的客户。
每次应用调用ACE_Reactor的handle_events方法,就从每个I/O句柄变为活动的客户那里读取一条日志记录。日志记录被写到服务器日志看守的标准输出。该输出可被重定向到多种设备,比如打印机、持久存储仓库或日志管理控制台。
 
 
图7-9 服务器日志看守中的组件
 
有若干C++类组件出现在日志服务体系中。在图7-9中使用Booch表示法[19]演示了多种组件间的继承和模板参数化关系。为增强复用和可扩展性,图中所示的组件被设计用以使服务器日志看守体系结构的以下方面去耦合:
 
反应堆构架组件(Reactor framework component):反应堆构架中的组件封装执行I/O多路分离和具体事件处理器分派的最底层机制。这些组件已在7.3中讨论。
 
连接相关组件(Connection-related component):这些通用模板实现接受器(Acceptor)模式[20],提供可复用的连接工厂组件。ACE_Acceptor是一个接受来自远地客户的网络连接、创建ACE_Svc_Handler的模板。ACE_Svc_Handler是与相连的客户交换数据的模板。这些组件在7.4.2.1中讨论。
 
应用特有组件(Application-specific component):这些组件实现分布式日志服务的应用特有的部分。Logging_Acceptor类给ACE_Acceptor提供具体的参数化类型,后者创建专用于日志应用的连接处理实例。同样地,Logging_Handler类也通过具体类型来实例化,这种具体类型提供必需的应用特有的功能,以接收和处理来自远地客户的日志记录。这些组件在7.4.2.2中讨论。
 
使用这样的高度去耦合的OO分解极大地增强了服务器日志看守的开发和可扩展性。这些组件的每一个被描述如下。

42/4<1234>
 

评分:0

我来说两句

seccode