2.3.2 体系结构模式
体系结构模式构建在上述讨论过的相对原始的体系结构元素之上,提供组合的、重复出现的结构,这些结构在给定的环境中能运行良好。它们未必是完整的解决方案,但当与其他模式组合时,它们会更好地引导设计者给出一个给定问题域的解决方案。
这是一个大的主题,已经有了许多用于分布式系统的体系结构模式。本节中,我们给出分布式系统中几个关键的体系结构模型,包括分层体系结构(layering architecture)、层次化体系结构(tiered architecture)和瘦客户相关的概念(包括虚拟网络计算的特定机制)。我们也把Web服务当做一个体系结构模式进行了考察,给出了其他可以应用在分布式系统中的模式。
分层 分层的概念是一个熟悉的概念,与抽象紧密相关。在分层方法中,一个复杂的系统被分成若干层,每层利用下层提供的服务。因此,一个给定的层提供一个软件抽象,更高的层不清楚实现细节,或不清楚在它下面的其他层。
就分布式系统而言,这等同于把服务垂直组织成服务层。一个分布式服务可由一个或多个服务器进程提供,这些进程相互交互,并与客户进程交互,维护服务中的资源在系统范围内的一致视图。例如,在互联网上基于网络时间 图2-7 分布式系统中软件和硬件服务层协议(Network Time Protocol,NTP)可实现一个网络时间服务,其中,服务器进程运行在互联网的主机上,给任一发出请求的客户提供当前的时间,51作为与服务器交互的结果,客户调整它们的当前时间。给定分布式系统的复杂性,这些服务组织成若干层经常是有帮助的。图2-7给出了一个分层体系结构的常规视图,并在第3~6章详细叙述这个视图的细节。
图2-7引入了重要的术语——平台和中间件,具体定义如下:
- 一个服务于分布式系统和应用的平台由最底层的硬件和软件层组成。这些底层为其上层提供服务,它们在每个计算机中都是独立实现的,提供系统的编程接口,方便进程之间的通信和协调。主要的例子有Intel x86/Windows、Intel x86/Solaris、Intel x86/Mac OS X、Intel x86/Linux和ARM/Symbian。
- 1.5.1节把中间件定义成一个软件层,其目的是屏蔽异构性,给应用程序员提供方便的编程模型。中间件表示成一组计算机上的进程或对象,这些进程或对象相互交互,实现分布式应用的通信和资源共享支持。中间件提供有用的构造块,构造在分布式系统中一起工作的软件组件。特别的,它通过对抽象的支持,如远程方法调用、进程组之间的通信、事件的通知、共享数据对象在多个协作的计算机上的分布、放置和检索、共享数据对象的复制以及多媒体数据的实时传送,提升应用程序通信活动的层次。我们将在下面的2.3.3节讲述这个重要的话题。
层次化体系结构 层次化体系结构与分层体系结构是互补的。分层将服务垂直组织成抽象层,而层次化是一项组织给定层功能的技术,它把这个功能放在合适的服务器上,或者作为第二选择放在物理结点上。这个技术与图2-7中所示的应用和服务的组织最相关,但它也可以应用到一个分布式系统体系结构的所有层。
我们先查看两层和三层体系结构概念。为了说明这些概念,考虑如下对一个给定应用的功能分解:
- 表示逻辑,涉及处理用户交互和修改呈现给用户的应用视图;
- 应用逻辑,涉及与应用相关的(也称为业务逻辑,虽然这个概念不仅仅限于业务应用)详细的应用特定处理;
- 数据逻辑,涉及应用的持久存储,通常在一个数据库管理系统中。
现在考虑用客户-服务器技术实现这样一个应用。图2-8a和图2-8b分别给出了相关的两层和三层体系结构解决方案,以便于比较。
在两层解决方案中,上面提及的三个方面必须被分到两个进程(客户和服务器)中。通常通过分隔应用逻辑来完成这个划分,把一些应用逻辑放在客户端,剩下的放在服务器端(虽然其他解决方案也是可以的)。这个模式的好处是具有交互的低延迟,仅有调用操作的消息交换,不足是将应用逻辑分离到不同的进程,带来的后果是一部分逻辑不能被另一部分直接调用。
在三层解决方案中,有从逻辑元素到物理服务器的一对一映射,因此,例如,应用逻辑放在一个地方,能提高软件的可维护性。每一层也都有定义明确的角色,例如,第三层仅仅是一个提供(可能是标准的)关系服务接口的数据库。第一层也可以是一个简单的用户界面,提供对瘦客户的内在支持(见下面的讨论)。缺点是增加了管理三个服务器的复杂性,也增加了与每个操作相关的网络流量和延迟。
注意这个方案可以推广到n层(或多层)的解决方案,其中一个给定的应用领域划分为n个逻辑元素,每个逻辑元素映射到一个给定的服务器元素。以维基百科基于Web的可供公众编辑的百科全书为例,它采用了多层次体系结构来处理大量的Web请求(每秒请求高达60000页)。
AJAX的作用:在1.6节中,我们介绍了AJAX(Asynchronous Javascript And XML)是Web所使用的标准客户-服务器交互方式的扩展。AJAX满足了Javascript前端程序(运行在Web浏览器中)和基于服务器的后端程序(拥有描述应用状态的数据)之间的细粒度通信的需要。概括而言,在标准的Web交互方式中,浏览器发送HTTP请求给服务器,请求给定URL的页面、图像或其他资源。服务器发送整个页面作为应答,这个页面或者从服务器上的一个文件中读取,或者由一个程序生成,取决于URL中可识别的资源类型。当客户收到内容时,浏览器根据其MIME类型(text/html、image/jpg等)相关的显示方式呈现它。虽然Web页面由不同类型的内容项组成,但是整个页面以它在html页面定义中指定的方式由浏览器组合并呈现。
这种标准的交互方式在几个重要的方面约束了Web应用的开发:
- 一旦浏览器发送了一个请求新Web页面的http请求,用户不能与该页面交互,直到新的html内容被浏览器收到并呈现。这个时间间隔是不确定的,因为它受限于网络和服务器延迟。
- 为了用来自服务器的额外数据修改当前页面的一小部分,也要请求和显示整个新的页面。这导致了对用户应答的延迟、客户和服务器两端的额外处理以及冗余的网络流量。
- 客户显示的页面内容不能被更新,从而不能响应服务器端拥有的应用数据的变化。
Javascript是一个跨平台、跨浏览器的编程语言,它能下载到浏览器中并执行,它的引入是去除这些约束的第一步。Javascript是一个通用的语言,它使得用户接口和应用逻辑能在浏览器窗口中被编程和执行。
AJAX是使得开发和部署交互型Web应用成为可能的第二步,它使得Javascript前端程序能直接从服务器程序中获得新的数据。任何数据项都能被请求,当前页有选择地更新来显示新的值。甚至,前端能以对应用有用的任何方式响应新的数据。
许多Web应用允许用户访问和更新大量共享的数据集,这些数据可能会改变以响应其他客户的输入或服务器收到的数据输入。它们要求一个及时的前端组件(运行在每个客户浏览器中)来完成用户接口动作(如菜单选择),也请求访问一个必须放在服务器上供共享的数据集。这样的数据集通常太大并且是动态的,所以不允许使用基于在用户会话(用于客户操纵)开始时下载整个应用状态副本给客户并供其操作的体系结构。
图2-9 AJAX举例:更新足球比分AJAX是支持构建这样的应用的“胶水”,它提供一套通信机制,使得运行在一个浏览器中的前端组件能发送请求,并从运行在服务器上的后端组件接收结果。客户通过Javascript XmlHttpRequest对象发送请求,该对象管理与一个服务器进程的HTTP交互(见1.6节)。因为XmlHttpRequest有一个复杂的API,且该API有些依赖浏览器,所以,通常通过众多可用于支持Web应用开发的Javascript库中的一个库访问它。图2-9展示了ATAX在Prototype.js Javascript库中的使用[www.prototypejs.org]。
这个例子是一个Web应用的片段,该应用显示足球比赛最新积分的页面。用户单击页面的相关行,55可以请求获得单个比赛的分数更新,其对应着执行示例程序的第一行。Ajax.Request对象发送一个HTTP请求给scores.php程序,该程序与Web页面位于相同的服务器上。Ajax.Request对象接着返回控制,允许浏览器继续应答相同窗口或其他窗口中其他用户的动作。当scores.php程序已经获得了最新的比分时,它在一个HTTP应答中返回该比分,因为它是一个onSuccess动作,所以,它分析结果并把比分插入到当前页面的相关位置。页面的其余部分不受影响,不被重载入。
这说明了在第一层组件和第二层组件之间使用的通信类型。虽然Ajax.Request(和下层的XmlHttpRequest对象)提供同步和异步通信,但总是使用异步版本,因为用户界面对延迟的服务器应答是不可接受的。
这个简单的例子说明了在两层应用中AJAX的使用。在三层应用中,服务器组件(在我们的例子中是scores.php)将发送一个请求给数据管理器组件(通常是发给数据库服务器的一个SQL查询)用于请求数据。这个请求是异步的,因为没有理由直到请求被满足后才返回控制给服务器。
AJAX机制组成了一项有效的技术,用于在具有不确定延迟的互联网环境下构造及时的Web应用,它已经得到了非常广泛的使用。Google地图应用[www.google.com Ⅱ]是一个突出的例子。地图作为一个连续的256×256像素图像(称为图片(tile))数组显示。当地图被移动时,浏览器中的Javascript代码重定位可见的图片,需要填入可见区域的额外的图片,可以通过AJAX调用到Google服务器去获取。图片一经收到就会显示出来,但浏览器在等待的时候可以继续应答用户的交互。
瘦客户 分布式计算的趋势是将复杂性从最终用户设备移向互联网服务。这点在向云计算(见第1章)发展的趋势中最明显,在上面讨论的层次化体系结构中也能看到。这个趋势导致了对瘦客户概念的兴趣,它使得能以很少的对客户设备的假设或需求,获得对复杂网络化服务的访问,这些服务可以通过云解决方案提供。更具体来说, 图2-10 瘦客户和计算机服务器术语瘦客户指的是一个软件层,在执行一个应用程序或访问远程计算机上的服务时,由该软件层提供一个基于窗口的本地用户界面。例如,图2-10给出了一个瘦客户,它在访问互联网上的一台计算服务器。这种方法的好处是有可能通过大量的网络化服务和潜在能力极大地增加简单的本地设备(例如,智能电话和其他资源有限的设备)。56瘦客户体系结构的主要缺点是:在交互频繁的图形活动(如CAD和图像处理)中,因为网络和操作系统的延迟,用户感受到的延迟会因为在瘦客户和应用进程之间传输图像和向量信息而增大到不可接受的程度。
这个概念导致虚拟网络计算(Virtual Network Computing,VNC)的出现。该项技术首先由Olivetti和Oracle研究实验室的研究者引入[Richardson et al.1998]。初始的概念已经演化成实现,例如,RealVNC[www.realvnc.com]提供了一个软件解决方案,Adventiq[www.adventiq.com]提供了一个基于硬件的解决方案,该方案支持在IP上传送键盘、视频和鼠标事件(KVM-over-IP)。其他VNC实现包括Apple Remote Desktop、TightVNC和Aqua Connect。
VNC在概念上是简单的,即为远程访问提供图形用户界面。在这个解决方案中,VNC客户(观众)通过VNC协议与VNC服务器交互。从图形支持角度看,协议在原语层次上操作,基于帧缓冲区,以以下操作为特色:在屏幕上的给定位置放置矩形像素数据(一些解决方案如Citrix的XenApp从窗口操作方面来看在较高层次操作[www.citrix.com])。这种低层方法确保协议能工作在任何操作系统或应用中。虽然这很直接,但它隐含着用户能用不同设备从任何地方访问他们的计算机设施,这代表了在移动计算方面迈出的重要的一步。
虚拟网络计算已经取代了网络计算机,后者是以前的瘦客户解决方案的实现方法,它通过简单、廉价、完全依赖网络化服务的硬件设备,从远程文件服务器下载它们的操作系统和用户所需的应用软件。因为所有的应用数据和代码由一个文件服务器存储,所以,用户可以从一个网络计算机迁移到另一个。事实上,虚拟网络计算被证明是一个更灵活的解决方案,现在主宰着市场。
其他经常出现的模式 如上所述,现在已有大量的体系结构模式,且它们已被文档化。这里给出一些关键的例子。
- 代理(proxy)模式是分布式系统中经常出现的模式,其主要用于支持远程过程调用或远程方法调用的位置透明性。用这种方法,一个代理在本地地址空间中被创建,用于代表远程对象。这个代理提供与远程对象一样的接口,程序员调用这个代理对象,因此无须了解交互的分布式特性。在RPC和RMI中,代理支持位置透明性的作用将在第5章做进一步的讨论。注意代理也被用于封装其他的功能(诸如复制或缓存的放置策略等)。
- Web服务中的业务代理(brokerage)的使用能被看成是一个在可能很复杂的分布式基础设施中支持互操作性的体系结构模式。特别地,57这个模式是由服务提供商、服务请求者和服务代理(提供与请求的服务一致的服务)三部分组成,如图2-11所示。这个业务代理模式在分布式系统的多个领域被多次应用,例如Java RMI中的注册服务、CORBA中的名字服务(分别参见第5章和第8章的讨论)。 图2-11 Web服务体系结构模式
- 反射(reflection)模式在分布式系统中作为支持内省(系统的动态发现的特性)和从中调停(动态修改结构或行为的能力)的手段而被持续地使用。例如,Java的内省能力被用于RMI的实现中,提供通用的分发(参见5.4.2节的讨论)。在一个反射系统中,标准的服务接口在基础层可供使用,但元层接口也可以提供对涉及服务实现的组件及组件参数的访问。许多技术在元层可用,包括截获到达的消息或调用、动态发现由给定对象提供的接口、发现和适应系统底层体系结构的能力。反射被应用于分布式系统中的多个领域,特别是反射中间件领域,例如,可以用于支持更多的可配置及重配置中间件体系结构[Kon et al.2001]。
与分布式系统相关的体系结构模式更多的例子可以在Bushmann等人[2007]的著作中找到。