架构风格是一组原则。你可以把它看成是一组为系统家族提供抽象框架的粗粒度模式。架构风格能改进分块,还能为频繁出现的问题提供解决方案,以此促进设计重用。
常见的软件体系结构风格涉及:
- 设计词汇表是什么?或者构件和连接器的类型是什么?
- 可容许的结构模式是什么?
- 基本的计算模型是什么?
- 风格的基本不变性是什么?
- 其使用的常见例子是什么?
- 使用此风格的优缺点是什么?
- 其常见特例是什么?
软件体系结构设计的一个中心问题是能否重用软件体系结构模式,或者采用某种软件体系结构风格。有原则地使用软件体系结构风格具有如下意义:
- 它促进了设计的复用,使得一些经过实践证实的解决方案能够可靠地解决新问题。
- 它能够带来显著的代码复用,使得体系结构风格中的不变部分可共享同一个解决方案。
- 便于设计者之间的交流与理解。
- 通过对标准风格的使用支持了互操作性,以便于相关工具的集成。
- 在限定了设计空间的情况下,能够对相关风格作出分析。
- 能够对特定的风格提供可视化支持。
与此同时,人们目前尚不能准确回答的问题是:
- 系统设计的哪个要点可以用风格来描述;
- 能否用系统的特性来比较不同的风格,如何确定用不同的风格设计系统之间的互操作;
- 能否开发出通用的工具来扩展风格;
- 如何为一个给定的问题选择恰当的体系结构风格,或者如何通过组合现有的若干风格来产生一个新的风格。
M.Shaw等人根据此框架给出了管道与过滤器、数据抽象和面向对象组织、基于事件的隐式调用、分层系统、仓库系统及知识库和表格驱动的解释器等一些常见的软件体系结构风格。
架构风格
客户端-服务器
将系统分为两个应用,其中客户端向服务器发送服务请求。基于组件的架构
把应用设计分解为可重用的功能、逻辑组件,这些组件的位置相互透明,只暴露明确定义的通信接口。分层架构
把应用的关注点分割为堆栈组(层)。消息总线
指接收、发送消息的软件系统,消息基于一组已知格式,以便系统无需知道实际接收者就能互相通信。N层/三层架构
用与分层风格差不多一样的方式将功能划分为独立的部分,每个部分是一个层,处于完全独立的计算机上。面向对象
该架构风格是将应用或系统任务分割成单独、可重用、可自给的对象,每个对象包含数据,以及与对象相关的行为。分离表现层
将处理用户界面的逻辑从用户界面(UI)视图和用户操作的数据中分离出来。面向服务架构(SOA)
是指那些利用契约和消息将功能暴露为服务、消费功能服务的应用。
这些架构风格分别适用于特定领域:
通信
SOA,消息总线,管道和过滤器部署
客户端/服务器,三层架构,N层架构领域
领域模型,网关交互
分离表现层结构
基于组件的架构,面向对象,分层架构
下面介绍几种常见的架构风格:
管道和过滤器风格
在管道/过滤器风格的软件体系结构中,每个构件都有一组输入和输出,构件读输入的数据流,经过内部处理,然后产生输出数据流。这个过程通常通过对输入流的变换及增量计算来完成,所以在输入被完全消费之前,输出便产生了。因此,这里的构件被称为过滤器,这种风格的连接件就像是数据流传输的管道,将一个过滤器的输出传到另一过滤器的输入。此风格特别重要的 过滤器必须是独立的实体,它不能与其它的过滤器共享数据,而且一个过滤器不知道它上游和下游的标识。一个管道/过滤器网络输出的正确性并不依赖于过滤器进 行增量计算过程的顺序。
图2-1是管道/过滤器风格的示意图。一个典型的管道/过滤器体系结构的例子是以Unix shell编写的程序。Unix既提供一种符号,以连接各组成部分(Unix的进程),又提供某种进程运行时机制以实现管道。另一个著名的例子是传统的编 译器。传统的编译器一直被认为是一种管道系统,在该系统中,一个阶段(包括词法分析、语法分析、语义分析和代码生成)的输出是另一个阶段的输入。
图 2‑1管道/过滤器风格的体系结构
管道/过滤器风格的软件体系结构具有许多很好的特点:
(1)使得软构件具有良好的隐蔽性和高内聚、低耦合的特点;
(2)允许设计者将整个系统的输入/输出行为看成是多个过滤器的行为的简单合成;
(3)支持软件重用。重要提供适合在两个过滤器之间传送的数据,任何两个过滤器都可被连接起来;
(4)系统维护和增强系统性能简单。新的过滤器可以添加到现有系统中来;旧的可以被改进的过滤器替换掉;
(5)允许对一些如吞吐量、死锁等属性的分析;
(6)支持并行执行。每个过滤器是作为一个单独的任务完成,因此可与其它任务并行执行。
但是,这样的系统也存在着若干不利因素。
(1)通常导致进程成为批处理的结构。这是因为虽然过滤器可增量式地处理数据,但它们是独立的,所以设计者必须将每个过滤器看成一个完整的从输入到输出的转换。
(2)不适合处理交互的应用。当需要增量地显示改变时,这个问题尤为严重。
(3)因为在数据传输上没有通用的标准,每个过滤器都增加了解析和合成数据的工作,这样就导致了系统性能下降,并增加了编写过滤器的复杂性
数据抽象与面向对象风格
抽象数据类型概念对软件系统有着重要作用,目前软件界已普遍转向使用面向对象系统。这种风格建立在数据抽象和面向对象的基础上,数据的表示方法和它们的相应操作封装在一个抽象数据类型或对象中。这种风格的构件是对象,或者说是抽象数据类型的实例。对象是一种被称作管理者的构件,因为它负责保持资源的完整性。对象是通过函数和过程的调用来交互的。
图2-2是数据抽象和面向对象风格的示意图。
图 2‑2数据抽象和面向对象风格的体系结构
面向对象的系统有许多的优点,并早已为人所知:
(1) 因为对象对其它对象隐藏它的表示,所以可以改变一个对象的表示,而不影响其它的对象。
(2) 设计者可将一些数据存取操作的问题分解成一些交互的代理程序的集合。
但是,面向对象的系统也存在着某些问题:
(1)为了使一个对象和另一个对象通过过程调用等进行交互,必须知道对象的标识。只要一个对象的标识改变了,就必须修改所有其他明确调用它的对象。
(2)必须修改所有显式调用它的其它对象,并消除由此带来的一些副作用。例如,如果A使用了对象B,C也使用了对象B,那么,C对B的使用所造成的对A的影响可能是料想不到的。
基于事件的隐式调用风格
基于事件的隐式调用风格的思想是构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其它构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,这样,一个事件的触发就导致了另一模块中的过程的调用。
从体系结构上说,这种风格的构件是一些模块,这些模块既可以是一些过程,又可以是一些事件的集合。过程可以用通用的方式调用,也可以在系统事件中注册一些过程,当发生这些事件时,过程被调用。
基于事件的隐式调用风格的主要特点是事件的触发者并不知道哪些构件会被这些事件影响。这样不能假定构件的处理顺序,甚至不知道哪些过程会被调用,因此,许多隐式调用的系统也包含显式调用作为构件交互的补充形式。
支持基于事件的隐式调用的应用系统很多。例如,在编程环境中用于集成各种工具,在数据库管理系统中确保数据的一致性约束,在用户界面系统中管理数据,以及在编辑器中支持语法检查。例如在某系 统中,编辑器和变量监视器可以登记相应Debugger的断点事件。当Debugger在断点处停下时,它声明该事件,由系统自动调用处理程序,如编辑程 序可以卷屏到断点,变量监视器刷新变量数值。而Debugger本身只声明事件,并不关心哪些过程会启动,也不关心这些过程做什么处理。
隐式调用系统的主要优点有:
(1)为软件重用提供了强大的支持。当需要将一个构件加入现存系统中时,只需将它注册到系统的事件中。
(2)为改进系统带来了方便。当用一个构件代替另一个构件时,不会影响到其它构件的接口。
隐式调用系统的主要缺点有:
(1)构件放弃了对系统计算的控制。一个构件触发一个事件时,不能确定其它构件是否会响应它。而且即使它知道事件注册了哪些构件的构成,它也不能保证这些过程被调用的顺序。
(2)数据交换的问题。有时数据可被一个事件传递,但另一些情况下,基于事件的系统必须依靠一个共享的仓库进行交互。在这些情况下,全局性能和资源管理便成了问题。
(3)既然过程的语义必须依赖于被触发事件的上下文约束,关于正确性的推理存在问题。
层次系统风格
层次系统组织成一个层次结构,每一层为上层服务,并作为下层客户。在一些层次系统中,除了一些精心挑选的输出函数外,内部的层只对相邻的层可见。这样的系统中构件在一些层实现了虚拟机(在另一些层次系统中层是部分不透明的)。连接件通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。
这种风格支持基于可增加抽象层的设计。这样,允许将一个复杂问题分解成一个增量步骤序列的实现。由于每一层最多只影响两层,同时只要给相邻层提供相同的接口,允许每层用不同的方法实现,同样为软件重用提供了强大的支持。
图2-3是层次系统风格的示意图。层次系统最广泛的应用是分层通信协议。在这一应用领域中,每一层提供一个抽象的功能,作为上层通信的基础。较低的层次定义低层的交互,最低层通常只定义硬件物理连接。
图 2‑3层次系统风格的体系结构
层次系统有许多可取的属性:
(1)支持基于抽象程度递增的系统设计,使设计者可以把一个复杂系统按递增的步骤进行分解;
(2)支持功能增强,因为每一层至多和相邻的上下层交互,因此功能的改变最多影响相邻的上下层;
(3)支持重用。只要提供的服务接口定义不变,同一层的不同实现可以交换使用。这样,就可以定义一组标准的接口,而允许各种不同的实现方法。
但是,层次系统也有其不足之处:
(1)并不是每个系统都可以很容易地划分为分层的模式,甚至即使一个系统的逻辑结构是层次化的,出于对系统性能的考虑,系统设计师不得不把一些低级或高级的功能综合起来;
(2)很难找到一个合适的、正确的层次抽象方法。
仓库风格
在仓库风格中,有两种不同的构件:中央数据结构说明当前状态,独立构件在中央数据存贮上执行,仓库与外构件间的相互作用在系统中会有大的变化。
控制原则的选取产生两个主要的子类。若输入流中某类时间触发进程执行的选择,则仓库是一传统型数据库;另一方面,若中央数据结构的当前状态触发进程执行的选择,则仓库是一黑板系统。
图2-4是黑板系统的组成。黑板系统的传统应用是信号处理领域,如语音和模式识别。另一应用是松耦合代理数据共享存取。
图 2‑4黑板系统的组成
我们从图2-4中可以看出,黑板系统主要由三部分组成:
(1)知识源。知识源中包含独立的、与应用程序相关的知识,知识源之间不直接进行通讯,它们之间的交互只通过黑板来完成。
(2)黑板数据结构。黑板数据是按照与应用程序相关的层次来组织的解决问题的数据,知识源通过不断地改变黑板数据来解决问题。
(3)控制。控制完全由黑板的状态驱动,黑板状态的改变决定使用的特定知识。
C2风格
C2体系结构风格可以概括为:通过连接件绑定在一起的按照一组规则运作的并行构件网络。C2风格中的系统组织规则如下:
(1)系统中的构件和连接件都有一个顶部和一个底部;
(2)构件的顶部应连接到某连接件的底部,构件的底部则应连接到某连接件的顶部,而构件与构件之间的直接连接是不允许的;
(3)一个连接件可以和任意数目的其它构件和连接件连接;
(4)当两个连接件进行直接连接时,必须由其中一个的底部到另一个的顶部。
图2-5是C2风格的示意图。图中构件与连接件之间的连接体现了C2风格中构建系统的规则。
图 2‑5 C2风格的体系结构
C2风格是最常用的一种软件体系结构风格。从C2风格的组织规则和结构图中,我们可以得出,C2风格具有以下特点:
(1)系统中的构件可实现应用需求,并能将任意复杂度的功能封装在一起;
(2)所有构件之间的通讯是通过以连接件为中介的异步消息交换机制来实现的;
(3)构件相对独立,构件之间依赖性较少。系统中不存在某些构件将在同一地址空间内执行,或某些构件共享特定控制线程之类的相关性假设。
二层C/S我们不再介绍了,直接说三层C/S
三层C/S的基本硬件结构
传统的二层C/S结构存在以下几个局限:
l 它是单一服务器且以局域网为中心的,所以难以扩展至大型企业广域网或Internet;
l 受限于供应商;
l 软、硬件的组合及集成能力有限;
l 难以管理大量的客户机。
因此,三层C/S结构应运而生。三层C/S结构是将应用功能分成表示层、功能层和数据层三部分。其解决方案是:对这三层进行明确分割,并在逻辑上使其独立。原来的数据层作为DBMS已经独立出来,所以关键是要将表示层和功能层分离成各自独立的程序,并且还要使这两层间的接口简洁明了。
将上述三层功能装载到硬件的方法基本上有三种(如图所示)。其中表示层配置在客户机中,而数据层配置在服务器中。
一般情况是只将表示层配置在客户机中,与二层C/S结构相比,其程序的可维护性要好得多,是其他问题并未得到解决。客户机的负荷太重,其业务处理所需的数据要从服务器传给客户机,所以系统的性能容易变坏。
如果将功能层和数据层分别放在不同的服务器中,则服务器和服务器之间也要进行数据传送。但是,由于在这种形态中三层是分别放在各自不同的硬件系统上的,所以灵活性很高,能够适应客户机数目的增加和处理负荷的变动。例如,在追加新业务处理时,可以相应增加装载功能层的服务器。因此,系统规模越大这种形态的优点就越显著。
值得注意的是:三层C/S结构各层间的通信效率若不高,即使分配给各层的硬件能力很强,其作为整体来说也达不到所要求的性能。此外,设计时必须慎重考虑三层间的通信方法、通信频度及数据量。这和提高各层的独立性一样是三层C/S结构的关键问题。
三层C/S的功能
1.表示层
表示层是应用的用户接口部分,它担负着用户与应用间的对话功能。它用于检查用户从键盘等输入的数据,显示应用输出的数据。为使用户能直观地进行操作,一 般要使用图形用户接口(GUI),操作简单、易学易用。在变更用户接口时,只需改写显示控制和数据检查程序,而不影响其他两层。检查的内容也只限于数据的 形式和值的范围,不包括有关业务本身的处理逻辑。
图形界面的结构是不固定的,这便于以后能灵活地进行变更。例如,在一个窗口中不是放入几个功能,而是按功能分割窗口,以便使每个窗口的功能简洁单纯。在这层的程序开发中主要是使用可视化编程工具。
2. 功能层
功能层相当于应用的本体,它是将具体的业务处理逻辑地编入程序中。例如,在制作订购合同的时要计算合同金额,按照定好的格式配置数据、打印订购合同,而 处理所需的数据则要从表示层或数据层取得。表示层和功能层之间的数据交往要尽可能简洁。例如,用户检索数据时,要设法将有关检索要求的信息一次传送给功能 层(参见图2),而由功能层处理过的检索结果数据也一次传送给表示层。在应用设计中,一定要避免进行一次业务处理,在表示层和功能层间进行多几次数据交换 的笨拙设计。
通常,在功能层中包含有:确认用户对应用和数据库存取权限的功能以及记录系统处理日志的功能。这层的程序多半是用可视化编程工具开发的,也有使用COBOL和C语言的。
3. 数据层
数据层就是DBMS,负责管理对数据库数据的读写。DBMS必须能迅速执行大量数据的更新和检索。现在的主流是关系数据库管理系统(RDBMS)。因此,一般从功能层传送到数据层的要求大都使用SQL语言。
三层C/S结构的优点
1。 具有灵活的硬件系统构成
对于各个层可以选择与其处理负荷和处理特性相适应的硬件。这是一个与系统可缩放性直接相关的问题。例如,最初用一台Unix工作站作为服务器,将数据层 和功能层都配置在这台服务器上。随着业务的发展,用户数和数据量逐渐增加,这时就可以将Unix工作站作为功能层的专用服务器,另外追加一台专用于数据层 的服务器。若业务进一步扩大,用户数进一步增加,则可以继续增加功能层的服务器数目,用以分割数据库。清晰、合理地分割三层结构并使其独立,可以使系统构 成的变更非常简单。因此,被分成三层的应用基本上不需要修正。
2。 提高程序的可维护性
三层C/S结构中,应用的各层可以并行开发,各层也可以选择各自最适合的开发语言。
3。 利于变更和维护应用技术规范
因为是按层分割功能,所以各个程序的处理逻辑变得十分简单。
4。 进行严密的安全管理
越关键的应用,用户的识别和存取权限设定愈重要。在三层C/S结构中,识别用户的机构是按层来构筑的,对应用和数据的存取权限也可以按层进行设定。例如,即使外部的入侵者突破了表示层的安全防线,若在功能层中备有另外的安全机构,系统也可以阻止入侵者进入其他部分。
此外,系统管理简单,可支持异种数据库,有很高的可用性。
C/S和B/S 的优缺点比较
C/S和B/S是当今世界开发模式技术架构的两大主流技术。C/S是美国 Borland公司最早研发,B/S是美国微软公司研发。目前,这两项技术以被世界各国所掌握,国内公司以C/S和B/S技术开发出产品也很多。这两种技术都有自己一定的市场份额和客户群,各家企业都说自己的管理软件架构技术功能强大、先进、方便,都能举出各自的客户群体,都有一大群文人墨客为自己摇旗呐 喊,广告满天飞,可谓仁者见仁,智者见智。
1、C/S架构软件的优势与劣势
(1)、应用服务器运行数据负荷较轻。
最简单的C/S体系结构的数据库应用由两部分组成,即客户应用程序和数据库服务器程序。二者可分别称为前台程序与后台程序。运行数据库服务器程序 的机器,也称为应用服务器。一旦服务器程序被启动,就随时等待响应客户程序发来的请求;客户应用程序运行在用户自己的电脑上,对应于数据库服务器,可称为 客户电脑,当需要对数据库中的数据进行任何操作时,客户程序就自动地寻找服务器程序,并向其发出请求,服务器程序根据预定的规则应答,送回结果,应用 服务器运行数据负荷较轻。
(2)、数据的储存管理功能较为透明。
在数据库应用中,数据的储存管理功能,是由服务器程序和客户应用程序分别独立进行的,前台应用可以违反的规则,并且通常把那些不同的(不管是已知 还是未知的)运行数据,在服务器程序中不集中实现,例如访问者的权限,编号可以重复、必须有客户才能建立定单这样的规则。所有这些,对于工作在前台程序上 的最终用户,是“透明”的,他们无须过问(通常也无法干涉)背后的过程,就可以完成自己的一切工作。在客户服务器架构的应用中,前台程序不是非常“瘦小 ”,麻烦的事情都交给了服务器和网络。在C/S体系的下,数据库不能真正成为公共、专业化的仓库,它受到独立的专门管理。
(3)、C/S架构的劣势是高昂的维护成本且投资大。
首先,采用C/S架构,要选择适当的数据库平台来实现数据库数据的真正“统一”,使分布于两地的数据同步完全交由数据库系统去管理,但逻辑上两地 的操作者要直接访问同一个数据库才能有效实现,有这样一些问题,如果需要建立“实时”的数据同步,就必须在两地间建立实时的通讯连接,保持两地的数据库服 务器在线运行,网络管理工作人员既要对服务器维护管理,又要对客户端维护和管理,这需要高昂的投资和复杂的技术支持,维护成本很高,维护任务量大。
其次,传统的C/S结构的软件需要针对不同的操作系统系统开发不同版本的软件,由于产品的更新换代十分快,代价高和低效率已经不适应工作需要。在JAVA这样的跨平台语言出现之后,B/S架构更是猛烈冲击C/S,并对其形成威胁和挑战。
2、B/S架构软件的优势与劣势
(1)、维护和升级方式简单。
目前,软件系统的改进和升级越来越频繁,B/S架构的产品明显体现着更为方便的特性。对一个稍微大一点单位来说,系统管理人员如果需要在几百甚至 上千部电脑之间来回奔跑,效率和工作量是可想而知的,但B/S架构的软件只需要管理服务器就行了,所有的客户端只是浏览器,根本不需要做任何的维护。无论 用户的规模有多大,有多少分支机构都不会增加任何维护升级的工作量,所有的操作只需要针对服务器进行;如果是异地,只需要把服务器连接专网即可,实现远程 维护、升级和共享。所以客户机越来越“瘦”,而服务器越来越“胖”是将来信息化发展的主流方向。今后,软件升级和维护会越来越容易,而使用起来会越来越简单,这对用户人力、物力、时间、费用的节省是显而易见的,惊人的。因此,维护和升级革命的方式是“瘦”客户机,“胖”服务器。
(2)、成本降低,选择更多。
大家都知道windows在桌面电脑上几乎一统天下,浏览器成为了标准配置,但在服务器操作系统上windows并不是处于绝对的统治地位。现在 的趋势是凡使用B/S架构的应用管理软件,只需安装在Linux服务器上即可,而且安全性高。所以服务器操作系统的选择是很多的,不管选用那种操作系统都 可以让大部分人使用windows作为桌面操作系统电脑不受影响,这就使的最流行免费的Linux操作系统快速发展起来,Linux除了操作系统是免费的 以外,连数据库也是免费的,这种选择非常盛行。
(3)、应用服务器运行数据负荷较重。
由于B/S架构管理软件只安装在服务器端(Server)上,网络管理人员只需要管理服务器就行了,用户界面主要事务逻辑在服务器 (Server)端完全通过WWW浏览器实现,极少部分事务逻辑在前端(Browser)实现,所有的客户端只有浏览器,网络管理人员只需要做硬件维护。 但是,应用服务器运行数据负荷较重,一旦发生服务器“崩溃”等问题,后果不堪设想。因此,许多单位都备有数据库存储服务器,以防万一。
C/S 与 B/S 区别
Client/Server是建立在局域网的基础上的,Browser/Server是建立在广域网的基础上的。
(1)硬件环境不同:
C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务。
B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例如电话上网, 租用设备, 信息自己管理, 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行。
(2)、对安全要求不同
C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强。 一般高度机密的信息系统采用C/S 结构适宜,可以通过B/S发布部分可公开信息。
B/S 建立在广域网之上, 对安全的控制能力相对弱, 面向是不可知的用户群。
(3)、对程序架构不同
C/S 程序可以更加注重流程,可以对权限多层次校验,对系统运行速度可以较少考虑。
B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上。 比C/S有更高的要求,B/S结构的程序架构是发展的趋势,从MS的。Net系列的BizTalk 2000 Exchange 2000等,全面支持网络的构件搭建的系统。SUN和IBM推的JavaBean构件技术等,使B/S更加成熟。
(4)、软件重用不同
C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好。
B/S 对的多重结构,要求构件相对独立的功能。 能够相对较好的重用。就如买来的餐桌可以再利用,而不是做在墙上的石头桌子。
(5)、系统维护不同
系统维护是软件生存周期中,开销大,相当重要。C/S 程序由于整体性,必须整体考察,处理出现的问题以及系统升级难, 可能是再做一个全新的系统。 B/S 构件组成方面构件个别的更换,实现系统的无缝升级。系统维护开销减到最小,用户从网上自己下载安装就可以实现升级。
(6)、处理问题不同
C/S 程序可以处理用户面固定,并且在相同区域, 安全要求高的需求,与操作系统相关, 应该都是相同的系统。 B/S 建立在广域网上, 面向不同的用户群,分散地域, 这是C/S无法作到的,与操作系统平台关系最小。
(7)、用户接口不同
C/S 多是建立在Window平台上,表现方法有限,对程序员普遍要求较高。 B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流, 并且大部分难度减低,降低开发成本。
(8)、信息流不同
C/S 程序一般是典型的中央集权的机械式处理,交互性相对低。 B/S 信息流向可变化, B-B、 B-C、 B-G等信息流向的变化, 更像交易中心。
基于层次消息总线的架构风格
JB/HMB风格的基本特征
目前对软件体系结构的研究集中在以下方面:各种体系结构风格的汇编和总结、体系结
构描述语言(architectural description languages,简称ADLS)、体系结构的形式化基础、体系结构分析技术、基于体系结构的软件开发、体系结构恢复和再工程、支持体系结构设计的工具和环境及特定领域的软件体系结构等。 青鸟工程在“九五”期间,对基于构件构架模式的软件工业化生产技术进行了研究,并实现了青鸟软件生产线系统151。以青鸟软件生产线的实践为背景,提出了基于层次消息总线的软件体系结构(Jade bird hierarchical message bus based style,以下简称JB/HMB风格),设计了相应的体系结构描述语言,开发了支持软件体系结构设计的辅助工具集,并研究了采用JB/HMB风格进行应用系统开发的过程框架。
JB/HMB风格的提出基于以下的实际背景:
(1) 随着计算机网络技术的发展,特别是分布式构件技术的日渐成熟和构件互操作标准的出现,如CORBA,DCOM和EJB等,加速了基于分布式构件的软件开发趋势,具有分布和并发特点的软件系统已成为一种普遍的应用需求。
(2) 基于事件驱动的编程模式已在图形用户界面程序设计中获得广泛应用。在此之前的
程序设计中,通常使用一个大的分支语句(switch Statement)控制程序的转移,对不同的输人情况分别进行处理,程序结构不甚清晰。基于事件驱动的编程模式在对多个不同事件响应的情况下,系统自动调用相应的处理函数,程序具有清晰的结构。
(3) 计算机硬件体系结构和总线的概念为软件体系结构的研究提供了很好的借鉴和启发,
在统一的体系结构框架下(即总线和接口规范),系统具有良好的扩展性和适应性。任何计算机厂商生产的配件,甚至是在设计体系结构时根本没有预料到的配件,只要遵循标准的接口规范,都可以方便地集成到系统中,对系统功能进行扩充,甚至是即插即用(即运行时刻的系统演化)。正是标准的总线和接口规范的制定,以及标准化配件的生产,促进了计算机硬件的产业分工和蓬勃发展。
JB/HMB风格基于层次消息总线、支持构件的分布和并发,构件之间通过消息总线进行通讯,如图所示。消息总线是系统的连接件,负责消息的分派、传递和过滤以及处理结果的返回。各个构件挂接在消息总线上,向总线登记感兴趣的消息类型。构件根据需要发出消息,由消息总线负责把该消息分派到系统中所有对此消息感兴趣的构件,消息是构件之间通讯的唯一方式,构件接收到消息后,根据自身状态对消息进行响应,并通过总线返回处理结果。由于构件通过总线进行连接,并不要求各个构件具有相同的地址空间或局限在一台机器上。该风格可以较好地刻画分布式并发系统,以及基于CORBA,DCOM和EJB规范的系统。
如图所示,系统中的复杂构件可以分解为比较低层的子构件,这些子构件通过局部消息
总线进行连接,这种复杂的构件称为复合构件。如果子构件仍然比较复杂,可以进一步分解。
如此分解下去,整个系统形成了树状的拓扑结构,树结构的末端结点称为叶结点,它们是系统中的原子构件,不再包含子构件,原子构件的内部可以采用不同于JB/HMB的风格,例如数据流风格、面向对象风格及管道/过滤器风格等,这些属于构件的内部实现细节。但要集成到JB/HMB风格的系统中,必须满足JB/HMB风格的构件模型的要求,主要是在接口规约方面的要求。另外,整个系统也可以作为一个构件,通过更高层的消息总线,集成更大的系统中。于是,可以采用统一的方式刻画整个系统和组成系统的单个构件。
构建模型
系统和组成系统的成分通常是比较复杂的,难以从一个视角获得对它们的完整理解,因
此一个好的软件工程方法往往从多个视角对系统进行建模,一般包括系统的静态结构、动态行为和功能等方面。例如,在Rumbaugh等人提出的OMT(object modeling technology)方法中,
采用了对象模型、动态模型和功能模型刻画系统的以上3个方面。
借鉴上述思想,为满足体系结构设计的需要,JB/HMB风格的构件模型包括了接口、静态结构和动态行为3个部分,如图所示。
在图中所示的构件模型中,左上方是构件的接口部分,一个构件可以支持多个不同的接口,每个接口定义了一组输入和输出的消息,刻画了构件对外提供的服务以及要求的环境服务,体现了该构件同环境的交互.右上方是用带输出的有限状态自动机刻画的构件行为,构件接收到外来消息后,根据当前所处的状态对消息进行响应,并可能导致状态的变迁.下方是复合构件的内部结构定义,复合构件是由更简单的子构件通过局部消息总线连接而成的.消息总线为整个系统和各个层次的构件提供了统一的集成机制。
构件接口
在体系结构设计层次上,构件通过接口定义了同外界的信息传递和承担的系统责任,构件接口代表了构件同环境的全部交互内容,也是唯一的交互途径.除此之外,环境不应对构件做任何其他与接口无关的假设,例如实现细节等。JB/HMB风格的构件接口是一种基于消息的互联接口,可以较好地支持体系结构设计。
构件之间通过消息进行通讯,接口定义了构件发出和接收的消息集合.同一般的互联接口相比.JB/HMB的构件接口具有两个显著的特点.首先,构件只对消息本身感兴趣,并不关心消息是如何产生的,消息的发出者和接收者不必知道彼此的情况,这样就切断了构件之间的直接联系,降低了构件之间的藕合强度,进一步增强了构件的复用潜力,并使得构件的替换变得更为容易。另外,在一般的互联接口定义的系统中,构件之间的连接是在要求的服务和提供的服务之间进行固定的匹配,而在JB/HMB的构件接口定义的系统中,构件对外来消息的响应,不但同接收到的消息类型相关,而且同构件当前所处的状态相关.构件对外来消息进行响应后,可能会引起状态的变迁.因此,一个构件在接收到同样的消息后,在不同时刻所处的不同状态下,可能会有不同的响应。
消息是关于某个事件发生的信息,上述接口定义中的消息分为两类:(i)构件发出的消息,通知系统中其他构件某个事件的发生或请求其他构件的服务;(ii)构件接收的消息,对系统中某个事件的响应或提供其他构件所需的服务.接口中的每个消息定义了构件的一个端口,具有互补端口的构件可以通过消息总线进行通讯,互补端口指的是除了消息进出构件的方向不同之外,消息名称、消息带有的参数和返回结果的类型完全相同的两个消息. 当某个事件发生后,系统或构件发出相应的消息,消息总线负责把该消息传递到对此消息感兴趣的构件.按照响应方式的不同,消息可分为同步消息和异步消息.同步消息是指消息的发送者必须等待消息处理结果返回才可以继续运行的消息类型.异步消息是指消息的发送者不必等待消息处理结果的返回即可继续执行的消息类型.常见的同步消息包括(一般的)过程调用。
消息总线
JB/HMB风格的消息总线是系统的连接件,构件向消息总线登记感兴趣的消息,形成构件-消息响应登记表.消息总线根据接收到的消息类型和构件一消息响应登记表的信息,定位并传递该消息给相应的响应者,并负责返回处理结果.必要时,消息总线还对特定的消息进行过滤和阻塞.下图给出了采用对象类符号表示的消息总线的结构。
运行时的演化
在许多重要的应用领域中,例如金融、电力、电信及空中交通管制等,系统的持续可用性是一个关键性的要求,运行时刻的系统演化可减少因关机和重新启动而带来的损失和风险。此外,越来越多的其他类型的应用软件也提出了运行时刻演化的要求,在不必对应用软件进行重新编译和加载的前提下,为最终用户提供系统定制和扩展的能力。JBI/HMB风格方便地支持运行时刻的系统演化,主要体现在以下3个方面:
(1) 动态增加或删除构件。在JB/HMB风格的系统中,构件接口中定义的输人和输出消息刻画了一个构件承担的系统责任和对外部环境的要求,构件之间通过消息总线进行通讯,彼此并不知道对方的存在。因此只要保持接口不变,构件就可以方便地替换。一个构件加人到系统中的方法很简单,只需向系统登记其所感兴趣的消息即可。但删除一个构件可能会引起系统中对于某些消息没有构件响应的异常情况,这时可以采取两种措施:一是阻塞那些没有构件响应的消息,二是首先使系统中的其他构件或增加新的构件对该消息进行响应,然后再删除相应的构件。系统中可能增删改构件的情况包括:当系统功能需要扩充时,往系统中增加新的构件。当对系统功能进行裁剪,或当系统中的某个构件出现问题时,需要删除系统中的某个构件。用带有增强功能或修正了错误的构件新版本代替原有的旧版本。
(2) 动态改变构件响应的消息类型。类似地,构件可以动态地改变对外提供的服务(即接收的消息类型),这时应通过消息总线对发生的改变进行重新登记。
(3) 消息过滤。利用消息过滤机制,可以解决某些构件集成的不匹配问题,详见“消息过滤”一节。消息过滤通过阻塞构件对某些消息的响应,提供了另一种动态改变构件对消息进行响应的方式。
JB/HMB风格的优点
以上讨论了JB/HMB风格的各组成要素,下面对JB/HMB风格的主要特点作总结。
(1) 从接口、结构和行为方面对构件进行刻画。在JB/HMB风格中,构件的描述包括接口、静态结构和动态行为3个方面。接口:构件可以提供一个或多个接口,每个接口定义了一组发送和接收的消息集合,刻画了构件对外提供的服务以及要求的环境服务,接口之间可以通过继承表达相似性。
静态结构:复合构件是由子构件通过局部消息总线连接而成的,形成该复合构件的内部结构。
动态行为:构件行为通过带输出的有限状态机刻画,构件接收到外来消息后,不但根
据消息类型,而且根据构件当前所处的状态对消息进行响应,并导致状态的变迁。
基于层次消息总线:消息总线是系统的连接件,负责消息的传递、过滤和分派,以及
处理结果的返回。各个构件挂接在总线上,向系统登记感兴趣的消息。构件根据需要发出消息,由消息总线负责把该消息分派到系统中对此消息感兴趣的所有构件。构件接收到消息后,根据自身状态对消息进行响应,并通过总线返回处理结果。由于构件通过总线进行连接,并不要求各个构件具有相同的地址空间或局限在一台机器上,系统具有并发和分布的特点。系统和复合构件可以逐层分解,子构件通过(局部)消息总线相连。每条消息总线分别属于系统和各层次的复合构件,我们把这种特征的总线称为层次消息总线。在系统开发方面,由于各层次的总线局部在相应的复合构件中,因此可以更好地支持系统的构造性和演化性。
统一描述系统和组成系统的构件:组成系统的构件通过消息总线进行连接,复杂构
件又可以分解为比较简单的子构件,通过局部消息总线进行连接,如果子构件仍然比较复杂,
可以进一步分解。系统呈现出树状的拓扑结构。另外,整个系统也可以作为一个构件,集成到更大的系统中。于是,就可以对整个系统和组成系统的各层构件采用统一的方式进行描述。
支持运行时刻的系统演化:系统的持续可用性是许多重要的应用系统的一个关键性
要求,运行时刻的系统演化可减少因关机和重新启动而带来的损失和风险。JB/HMB风格方便地支持运行时刻的系统演化,主要包括动态增加或删除构件、动态改变构件响应的消息类型和消息过滤。
REST架构风格
首先,REST是Web自身的架构风格。REST也是Web之所以取得成功的技术架构方面因素的总结。REST是世界上最成功的分布式应用架构风格(成功案例:Web,还不够吗?)。它是为运行在互联网环境 的 分布式 超媒体系统量身定制的。互联网环境与企业内网环境有非常大的差别,最主要的差别是两个方面:
- 可伸缩性需求无法控制:并发访问量可能会暴涨,也可能会暴跌。
- 安全性需求无法控制:无法控制客户端发来的请求的格式,很可能会是恶意的请求。
而所谓的“超媒体系统”,即,使用了超文本的系统。可以把“超媒体”理解为超文本+媒体内容。
REST是HTTP/1.1协议等Web规范的设计指导原则,HTTP/1.1协议正是为实现REST风格的架构而设计的。新的Web规范,其设计必须符合REST的要求,否则整个Web的体系架构会因为引入严重矛盾而崩溃。这句话不是危言耸听,做个类比,假如苏州市政府同意在市区著名园林的附近大型土木,建造大量具有后现代风格的摩天大楼,那么不久之后世界闻名的苏州园林美景将不复存在。
上述这些关于“REST是什么”的描述,可以总结为一句话:REST是所有Web应用都应该遵守的架构设计指导原则。当然,REST并不是法律,违反了REST的指导原则,仍然能够实现应用的功能。但是违反了REST的指导原则,会付出很多代价,特别是对于大流量的网站而言。
要深入理解REST,需要理解REST的五个关键词:
- 资源(Resource)
- 资源的表述(Representation)
- 状态转移(State Transfer)
- 统一接口(Uniform Interface)
- 超文本驱动(Hypertext Driven)
什么是资源?
资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。
什么是资源的表述?
资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交换)。资源的表述可以有多种格式,例如HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。
什么是状态转移?
状态转移(state transfer)与状态机中的状态迁移(state transition)的含义是不同的。状态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资源的表述,来间接实现操作资源的目的。
什么是统一接口?
REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。以HTTP/1.1协议为例,HTTP/1.1协议定义了一个操作资源的统一接口,主要包括以下内容:
- 7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS
- HTTP头信息(可自定义)
- HTTP响应状态代码(可自定义)
- 一套标准的内容协商机制
- 一套标准的缓存机制
- 一套标准的客户端身份认证机制
REST还要求,对于资源执行的操作,其操作语义必须由HTTP消息体之前的部分完全表达,不能将操作语义封装在HTTP消息体内部。这样做是为了提高交互的可见性,以便于通信链的中间组件实现缓存、安全审计等等功能。
什么是超文本驱动?
“超文本驱动”又名“将超媒体作为应用状态的引擎”(Hypermedia As The Engine Of Application State,来自Fielding博士论文中的一句话,缩写为HATEOAS)。将Web应用看作是一个由很多状态(应用状态)组成的有限状态机。资源之间通过超链接相互关联,超链接既代表资源之间的关系,也代表可执行的状态迁移。在超媒体之中不仅仅包含数据,还包含了状态迁移的语义。以超媒体作为引擎,驱动Web应用的状态迁移。通过超媒体暴露出服务器所提供的资源,服务器提供了哪些资源是在运行时通过解析超媒体发现的,而不是事先定义的。从面向服务的角度看,超媒体定义了服务器所提供服务的协议。客户端应该依赖的是超媒体的状态迁移语义,而不应该对于是否存在某个URI或URI的某种特殊构造方式作出假设。一切都有可能变化,只有超媒体的状态迁移语义能够长期保持稳定。
理解REST风格的架构所具有的6个的主要特征:
- 面向资源(Resource Oriented)
- 可寻址(Addressability)
- 连通性(Connectedness)
- 无状态(Statelessness)
- 统一接口(Uniform Interface)
- 超文本驱动(Hypertext Driven)
这6个特征是REST架构设计优秀程度的判断标准。其中,面向资源是REST最明显的特征,即,REST架构设计是以资源抽象为核心展开的。可寻址说的是:每一个资源在Web之上都有自己的地址。连通性说的是:应该尽量避免设计孤立的资源,除了设计资源本身,还需要设计资源之间的关联关系,并且通过超链接将资源关联起来。无状态、统一接口是REST的两种架构约束,超文本驱动是REST的一个关键词,在前面都已经解释过,就不再赘述了。
从架构风格的抽象高度来看,常见的分布式应用架构风格有三种:
- 分布式对象(Distributed Objects,简称DO)
架构实例有CORBA/RMI/EJB/DCOM/.NET Remoting等等
- 远程过程调用(Remote Procedure Call,简称RPC)
架构实例有SOAP/XML-RPC/Hessian/Flash AMF/DWR等等
- 表述性状态转移(Representational State Transfer,简称REST)
架构实例有HTTP/WebDAV
DO和RPC这两种架构风格在企业应用中非常普遍,而REST则是Web应用的架构风格,它们之间有非常大的差别。
REST与DO的差别在于:
- REST支持抽象(即建模)的工具是资源,DO支持抽象的工具是对象。在不同的编程语言中,对象的定义有很大差别,所以DO风格的架构通常都是与某种编程语言绑定的。跨语言交互即使能实现,实现起来也会非常复杂。而REST中的资源,则完全中立于开发平台和编程语言,可以使用任何编程语言来实现。
- DO中没有统一接口的概念。不同的API,接口设计风格可以完全不同。DO也不支持操作语义对于中间组件的可见性。
- DO中没有使用超文本,响应的内容中只包含对象本身。REST使用了超文本,可以实现更大粒度的交互,交互的效率比DO更高。
- REST支持数据流和管道,DO不支持数据流和管道。
- DO风格通常会带来客户端与服务器端的紧耦合。在三种架构风格之中,DO风格的耦合度是最大的,而REST的风格耦合度是最小的。REST松耦合的源泉来自于统一接口+超文本驱动。
REST与RPC的差别在于:
- REST支持抽象的工具是资源,RPC支持抽象的工具是过程。REST风格的架构建模是以名词为核心的,RPC风格的架构建模是以动词为核心的。简单类比一下,REST是面向对象编程,RPC则是面向过程编程。
- RPC中没有统一接口的概念。不同的API,接口设计风格可以完全不同。RPC也不支持操作语义对于中间组件的可见性。
- RPC中没有使用超文本,响应的内容中只包含消息本身。REST使用了超文本,可以实现更大粒度的交互,交互的效率比RPC更高。
- REST支持数据流和管道,RPC不支持数据流和管道。
- 因为使用了平台中立的消息,RPC风格的耦合度比DO风格要小一些,但是RPC风格也常常会带来客户端与服务器端的紧耦合。支持统一接口+超文本驱动的REST风格,可以达到最小的耦合度。
比较了三种架构风格之间的差别之后,从面向实用的角度来看,REST架构风格可以为Web开发者带来三方面的利益:
- 简单性
采用REST架构风格,对于开发、测试、运维人员来说,都会更简单。可以充分利用大量HTTP服务器端和客户端开发库、Web功能测试/性能测试工具、HTTP缓存、HTTP代理服务器、防火墙。这些开发库和基础设施早已成为了日常用品,不需要什么火箭科技(例如神奇昂贵的应用服务器、中间件)就能解决大多数可伸缩性方面的问题。
- 可伸缩性
充分利用好通信链各个位置的HTTP缓存组件,可以带来更好的可伸缩性。其实很多时候,在Web前端做性能优化,产生的效果不亚于仅仅在服务器端做性能优化,但是HTTP协议层面的缓存常常被一些资深的架构师完全忽略掉。
- 松耦合
统一接口+超文本驱动,带来了最大限度的松耦合。允许服务器端和客户端程序在很大范围内,相对独立地进化。对于设计面向企业内网的API来说,松耦合并不是一个很重要的设计关注点。但是对于设计面向互联网的API来说,松耦合变成了一个必选项,不仅在设计时应该关注,而且应该放在最优先位置。
架构风格和架构模式之间的细微差别
- 架构风格是系统主要的、组织性的设计。
- 架构模式从子系统或模块、及其之间的关系层次上描述了粗粒度的解决方案。
- 系统隐喻则更为概念化,比起软件工程概念,它更多地涉及现实世界的概念。
David Calvert在1996年给出了一份架构风格/模式的部分清单:
- 数据流系统——批处理,管道-过滤器。
- 调用-返回系统——主程序和子程序,面向对象系统,分层。
- 独立组件——通信过程,事件系统。
- 虚拟机——解释器,基于规则的系统。
- 以数据为中心的系统(仓库)——数据库,超文本系统,黑板。
其它比较现代的风格/模式还有:插件、点对点、无共享架构、表述性状态转移(REST)、前端-后端。在维基百科上有更为完整的列表。