第 1 章 ACE 自适配通信环境:用于开发通信软件的面向对象网络编
程工具包
Douglas C. Schmidt
摘 要
ACE
自适配通信环境(
Adaptive Communication Environment
)是一种面向对象(
OO
)的工具包,它
实现了通信软件的许多基本的设计模式。
ACE
的目标用户是在
UNIX
和
Win32
平台上开发高性能通信服
务和应用的开发者。
ACE
简化了使用进程间通信、事件多路分离、显式动态链接和并发的
OO
网络应用
和服务的开发。通过在运行时将服务与应用动态链接进应用,并在一个或多个进程或线程中执行这些服
务,
ACE
使系统的配置和重配置得以自动化。
本论文描述
ACE
的结构和功能,并使用来自像电信、企业级医学成像和
WWW
服务这样的领域的例
子阐释核心的
ACE
特性。
ACE
可以自由使用,并正在被用于许多商业项目(比如爱立信、
Bellcore
、西
门子、摩托罗拉、柯达,和
McDonnell Douglas
),以及许多学院和工业研究项目。
ACE
已被移植到多种
OS
(操作系统)平台上,包括
Win32
和大多数的
UNIX/POSIX
实现。此外,同时有
C++
和
Java
版本的
A
CE
可用。
1.1 介绍
1.1.1 问题:分布式软件危机
对健壮的和高性能的分布式计算系统的需求一直在稳定地增长。这些类型的系统的例子包括全球个
人通信系统、网络管理平台,企业级医学成像系统、在线金融分析系统,以及实时航空控制系统。对于
以下方面来说,分布式计算是一种有前途的技术:通过连接性和相互配合促进协作;通过并行处理改善
性能;通过复制改善可靠性和可用性;通过模块性改善可伸缩性和可移植性;通过动态配置和重配置改
善可扩展性;以及通过资源共享和开发系统提高成本效用。
尽管分布式计算提供了许多潜在的好处,开发通信软件仍然是昂贵而易错的。面向对象编程语言、
组件和框架(Framework)是被广泛鼓吹的、用以降低软件成本并提高软件质量的技术。去除那些过分的
宣传,OO 的主要好处源于对模块性和可扩展性的强调,它将易变的实现细节封装在稳定的接口后面,并
增强了软件的复用。
多年来,在某些已被广泛探索的领域中的开发者已经成功地应用了 OO 技术和工具。例如,Microso
ft MFC GUI 框架和 OCX 组件是 PC 平台上用于创建图形商业应用的事实上的工业标准。尽管这些工具
有着自身的局限,它们仍然演示了复用通用框架和组件的生产效率优势。
2
在像电信、医学成像、航空控制和在线事务处理这样的更复杂的领域中,软件开发者历来就缺少标
准的、成型的中间件组件。结果,开发者在很大程度上是从头开始构建、验证和维护软件系统。在一个
政府经济干预减少的艰难的全球竞争时代,这样的作坊式开发过程正在变得难以容忍的昂贵和费时。在
业界,这样的情形导致了一场“分布式软件危机”:计算硬件和网络在变小、变快、变得更为便宜;而分
布式软件的开发和维护在变大、变慢、变得更为昂贵。
构建分布式软件的挑战源于与分布式系统相关联的
固有的
和
非固有的
复杂性[1]。固有的复杂性源于
开发分布式软件的基本的挑战,其中主要的有:检测和恢复网络及主机失败、最小化通信响应延迟的影
响,以及确定服务组件和工作负载在网络的处理单元上的最优划分。
非固有的复杂性源于用以开发分布式软件的工具和技术的局限。例如,许多标准的网络机制(比如 s
ocket[2]和 TLI[3])和可复用组件库(比如 X windows 和 Sun RPC)缺乏类型安全的、可移植的、可重入
的和可扩展的
应用编程接口
(API)。同样地,通用网络编程接口,如 socket 和 TLI,使用弱类型的整型
句柄,可能会导致微妙的运行时错误[4]。
复杂性的另一来源起因于算法分解的普遍使用[5],它致使软件系统不可扩展和不可复用[6]。尽管图
形用户接口(GUI)普遍采用面向对象技术构建,典型的分布式软件通常仍然使用算法分解进行开发。在
一些流行的网络编程教科书[7, 8, 3]中的例子基于面向算法的设计和实现技术,从而更加恶化了前述问
题。
可扩展性和最大限度复用的缺乏对于复杂的分布式软件是特别成问题的。可扩展性是确保服务和特
性的及时修改和增强的基本要求。复用是有效利用专家开发者的领域知识、以避免重新开发和重新验证
“反复出现的需求和软件挑战的通用解决方案”的基本要求。
1.1.2 解决方案:面向对象的设计模式和框架
面向对象的设计模式和框架有助于减少对分布式软件的核心概念和抽象的昂贵的重新发现和发明,
它们因此而备受重视。模式提供了一种封装设计知识的方法,这些设计知识为标准的分布式软件开发问
题提供解决方案[9]。例如,模式对于描述重复出现的“
微型结构
”(比如反应器(Reactor)[10]和主动对
象(Active Object)[11])十分有用,这些微型结构是对一些已被证明可用于构建分布式通信软件的通用
对象结构的抽象。但是,被文档化为模式的抽象并不直接产生可复用代码。因此,有必要通过
框架
的创
建和使用来增加对模式的研究。
通过集成成组的抽象类,并定义这些类的协作的标准途径,框架为应用提供了可复用的软件组件[12]。
框架实例化设计模式族,以帮助开发者避免对通用分布式软件组件的昂贵的重新发明。其成果是“半完
成”的应用骨架,它可以通过继承和实例化框架中的可复用“积木”组件来进行定制。因为框架与关键
的分布式编程任务(比如服务初始化、错误处理、流控制、事件多路分离、并发控制)紧密地集成在一
起,复用的范围可以显著地大于使用传统函数库,甚或是通常的 OO 类库。
本论文被组织如下:1.2 给出 ACE 工具包的结构和功能的综述;1.3 详细描述 ACE C++包装组件和
较高级的 ACE 框架组件及模式;1.4 检查若干使用 ACE 构建的网络应用的实现;还有 1.5 给出结束语
1.2 ACE 综述
为阐释 OO 模式和框架是怎样被成功地应用于分布式软件的,本论文考查自适配通信环境(ACE)[6]。
ACE 是可以自由使用的 OO 工具包,其中包含有丰富的、可跨越广泛的 OS 平台执行通用网络编程任务
3
的可复用包装、类属,以及框架。ACE 提供的任务包括:
z
事件多路分离和事件处理器分派
[13, 14, 10, 15];
z
连接建立和服务初始化
[16, 17, 18];
z
进程间通信
[19, 4]
和共享内存管理
;
z
分布式通信服务的动态配置
[20, 21];
z
并发
/
并行和同步
[22, 23, 11, 24];
z
更高级的分布式服务组件
(比如名字服务、事件服务、日志服务、时间服务和令牌服务)。
图 1-1 ACE 自适配通信环境中的组件
ACE 工具包的设计采用分层的体系结构。图 1-1 演示了 ACE 组件间的纵向和横向关系。ACE 的较低
层是封装现有的 OS 网络编程机制的 OO
包装
(wrapper)。ACE 的高层扩展这些包装,以提供 OO
框架
和
组件
、覆盖更为广泛的面向应用的网络任务和服务。这一部分的余下部分给出对 ACE 中类属的结构和功
能的综述(如图 1-2 所示)。1.3 提供了对 ACE 的网络编程特性和组件的深入讨论。
贯穿本论文,ACE 组件通过 Booch 表示法[5]来进行图解。实心矩形表示类属,它将一定数量的相关
类合成进一个公共的名字空间。实心云表示对象;如嵌套则表示对象间的合成关系;而无方向的边表示
在两个对象间存在某种类型的链接。虚线云表示类;有向边表示类之间的继承关系;而一端有小圆圈的
无向边表示两个类之间的合成或是使用关系。在三角形内标记的“A”标识一个类为
抽象类
[25]。抽象类不
能被直接实例化,而必须被子类化。在实例化抽象类子类的任何对象之前,该子类必须提供所有抽象方
法的定义。
1
1
通常 C++把抽象方法称为
纯虚函数
(pure virtual function)
4
1.2.1 ACE OS 适配层
ACE 的源码树含有超过 85,000 行 C++代码。其中大约 9,000 行代码(也就是,大约为总数的 10%)
为 OS
适配层
所特有。该层将 ACE 的较高层和与下列 OS 机制相关联的平台特有的依赖屏蔽开来:
z 多线程和同步
z 进程间通信
z 事件多路分离
z 显式动态链接
z 内存映射文件和共享内存
图 1-2 ACE 中的类属
1.2.2 ACE OO 包装
在 OS 适配层之上是许多 OO 包装,它们封装并增强在像 Win32 和 UNIX 这样的现代操作系统上可
用的并发、进程间通信(IPC)、以及虚拟内存机制(在图 1-1 底部演示)。应用可以通过有选择地继承、
聚合(aggregating)、和/或实例化下列 ACE 包装类属来合并和编写这些组件:
5