1.5 挑战
1.2节的例子试图说明分布式系统的范围,并提出在设计中出现的问题。在许多系统中,遇到了重大的挑战并且已经得到解决。随着分布式系统的应用范围和规模的扩展,可能会遇到相同的和其他的挑战。本节我们描述主要的挑战。
1.5.1 异构性
互联网使得用户能在大量异构计算机和网络上访问服务和运行应用程序。下面这些均存在异构性(即存在多样性和差别):
- 网络;
- 计算机硬件;
- 操作系统;
- 编程语言;
- 由不同开发者完成的软件实现。
虽然互联网由多种不同种类的网络组成(见图1-3),但因为所有连接到互联网的计算机都使用互联网协议来相互通信,所以这些不同网络的区别被屏蔽了。例如,连接在以太网中的计算机要在以太网上实现互联网协议,而在另一种网络上的计算机需要在该网络上实现互联网协议。第3章将解释互联网协议如何在多种不同的网络上实现。16
整型等数据类型在不同种类的硬件上可以有不同的表示方法。例如,整数的字节顺序就有两种表示方法。如果要在不同硬件上运行的两个程序之间交换消息,那么就要处理它们在表示上的不同。
虽然互联网上所有计算机的操作系统均需要包含互联网协议的实现,但可以不为这些协议提供相同的应用编程接口。例如,UNIX中消息交换的调用与Windows中的调用是不一样的。
不同的编程语言使用不同的方式表示字符和数据结构(如数组和记录)。如果想让用不同语言编写的程序能够相互通信,那么必须解决这些差异。
不同开发者只有使用公共标准,他们编写的程序才能相互通信。例如,网络通信和消息中的基本数据项和数据结构的表示均要使用公共标准。所以,要制订和采用公共标准,就像互联网协议一样。
中间件 术语中间件是指一个软件层,它提供了一个编程抽象,同时屏蔽了底层网络、硬件、操作系统和编程语言的异构性。第4、5和8章描述的公共对象请求代理(Common Object Request Broker,CORBA)就是一个中间件。有些中间件,如Java远程方法调用(Remote Method Invocation,RMI)(见第5章),仅支持一种编程语言。大多数中间件在互联网协议上实现,由这些协议屏蔽了底层网络的差异,但所有的中间件要解决操作系统和硬件的不同,如何做到这一点将是第4章讨论的主题。
除了解决异构性的问题外,中间件为服务器和分布式应用的程序员提供了一致的计算模型。这些模型包括远程对象调用、远程事件通知、远程SQL访问和分布式事务处理。例如,CORBA提供了远程对象调用,它允许在一台计算机上运行的程序中的对象调用在另一台计算机上运行的某个程序中的一个对象的方法。它从实现上屏蔽了为了发送调用请求和应答,消息通过网络传递的事实。
异构性和移动代码 术语移动代码指能从一台计算机发送到另一台计算机,并在目的计算机上运行的代码,Java applet是一个例子。适合在一种计算机上运行的代码未必适合在另一种计算机上运行,因为可执行程序通常依赖于计算机的指令集和操作系统。
虚拟机方法提供了一种使代码可在任何计算机上运行的方法:某种语言的编译器生成一台虚拟机的代码而不是某种硬件代码,例如,Java编译器生成Java虚拟机的代码,虚拟机通过解释的方式来执行它。为了使Java程序能运行,要在每种计算机上实现一次Java虚拟机。
今天,最常使用的移动代码是将一些Web页面的JavaScript程序装载到客户浏览器中。Web技术在这方面的扩展将在1.6节做进一步讨论。
1.5.2 开放性
计算机系统的开放性是决定系统能否以不同的方式被扩展和重新实现的特征。分布式系统的开放性主要取决于新的资源共享服务能被增加和供多种客户程序使用的程度。17
除非软件开发者能获得系统组件的关键软件接口的规约和文档,否则无法实现开放性。一句话,发布关键接口。这个过程类似接口的标准化,但它经常避开官方的标准化过程,官方的标准化过程通常烦琐且进度缓慢。
然而,发布接口仅是分布式系统增加和扩展服务的起点。设计者所面临的挑战是解决由不同人构造的由许多组件组成的分布式系统的复杂性。
互联网协议的设计者引入了一系列称为“征求意见文档”(Requests For Comments,RFC)的文档,每个文档有一个编号。20世纪80年代早期发布了互联网通信协议的规约,并放入RFC中,中期发布了在互联网上运行的应用的规约,如文件传输规约、电子邮件规约和telnet规约。这种活动一直在继续,形成了互联网技术文档的基础。除了协议规约外,该序列还包含讨论。读者可从[www.ietf.org]获得这些资料。最初的互联网通信协议的发布使得各种互联网系统和应用(包括Web)应运而生。RFC不是唯一的发布方式,例如,万维网联盟(World Wide Web Consortium,W3C)开发和发布了与Web工作相关的标准[www.w3.org]。
按这种方式支持资源共享的系统之所以称为开放的分布式系统,主要是强调它们是可扩展的。它们可通过在网络中增加计算机实现在硬件层次上的扩展,通过引入新的服务、重新实现旧的服务实现在软件层次上的扩展,最终使得应用程序能共享资源。开放系统常被提到的另一个好处是它们与销售商无关。
开放的分布式系统的特征总结如下:
- 发布系统的关键接口是开放系统的特征。
- 开放的分布式系统是基于一致的通信机制和发布接口访问共享资源的。
- 开放的分布式系统能用不同销售商提供的异构硬件和软件构造,但如果想让系统正确工作,就要仔细测试和验证每个组件与发布的标准之间的一致性。
1.5.3 安全性
分布式系统中维护和使用的众多信息资源对用户具有很高的内在价值,因此它们的安全相当重要。信息资源的安全性包括三个部分:机密性(防止泄露给未授权的个人)、完整性(防止被改变或被破坏)、可用性(防止对访问资源的手段的干扰)。
1.1节指出,虽然互联网允许一台计算机中的程序与另一台计算机上的程序通信,而且可以不考虑它们的位置,18但安全风险与允许自由访问企业内部网内的所有资源相关。虽然防火墙能形成保护企业内部网的屏障,限制进出企业内部网的流量,但这不能确保企业内部网的用户恰当地使用资源,或恰当地使用互联网的资源,后一种资源不受防火墙保护。
在分布式系统中,客户发送请求去访问由服务器管理的数据,这涉及在网络上通过消息发送信息。例如:
1)医生可能请求访问医院病人的数据或发送新增的病人数据。
2)在电子商务和电子银行中,用户在互联网上发送信用卡号码。
上面两个例子所面临的挑战是以安全的方式在网络上通过消息发送敏感信息。但安全性不只是涉及对消息的内容保密,它还涉及确切知道用户或代表用户发送消息的其他代理的身份。在第一个例子中,服务器要知道用户确实是一个医生;在第二个例子中,用户要确保他们正在交易的商店或银行的身份正确。这里,所面临的第二个挑战是正确地识别远程用户或其他代理的身份。利用加密技术可满足这两个挑战。加密技术被广泛使用在互联网上,第11章将讨论这个问题。
然而,下列两个安全方面所面临的挑战目前还没有圆满解决:
拒绝服务攻击:另一个安全问题是出于某些原因用户可能希望中断服务。可用下面的方法实现这个目的:用大量无意义的请求攻击服务,使得重要的用户不能使用它。这称为拒绝服务攻击。已发生几起对几个众所周知的Web服务进行的拒绝服务攻击。现在通过在事件发生后抓获和惩罚犯罪者来解决这种攻击,但这不是解决这种问题的通用方法。以改善网络管理为根本的反击手段正在开发过程中,第3章会讲解这些问题。
移动代码的安全性:移动代码需要小心处理。设想用户接收到一个作为电子邮件附件发送的可执行程序,那么运行该程序会带来的后果是不可预测的。例如,它可能看似显示了一幅有趣的画,但实际上它可能在访问本地资源,或可能是拒绝服务攻击的一部分。确保移动代码安全的一些手段会在第11章中谈到。
1.5.4 可伸缩性
分布式系统可在不同的规模(从小型企业内部网到互联网)下有效且高效地运转。如果资源数量和用户数量激增,系统仍能保持其有效性,那么该系统就称为可伸缩的。互联网上计算机数量和服务器数量不断增长。图1-6列出到2005年为止Web出现的12年间计算机和Web服务器数量的增长情况[zakon.org]。值得一提的是,在此期间计算机和Web服务器有巨大的增长,而相关的百分比却趋于平稳,这个趋势可以用固定和移动个人计算的增长来解释。19一个Web服务器也可以越来越多地部署在多个计算机上。
可伸缩分布式系统的设计面临下列挑战:
控制物理资源的开销:当对资源的需求增加时,应该可以花费合理的开销扩展系统以满足要求。例如,在企业内部网上文件被访问的频率可能随用户和计算机数量的增加而增加。如果一台文件服务器不能处理所有的文件访问请求,那么必须能增加服务器数量以避免可能出现的性能瓶颈。通常,要使有n个用户的系统成为可伸缩的,那么所需的物理资源数量应该至多为O(n),即正比于n。例如,如果一个文件服务器能支持20个用户,那么两台这样的服务器应该能支持40个用户。虽然这听起来好像是理所当然的目标,但实际上未必容易达到,具体内容请参见第12章。
控制性能损失:如果数据集的大小与系统中的用户或资源数量成正比,设想一下这些数据的管理,例如,记录计算机的域名和对应的由域名系统持有的互联网地址的表,这种表主要用于查找如www.amazon.com这样的DNS名字。采用层次结构的算法其伸缩性要好于使用线性结构的算法。但即使使用层次结构,数量的增加仍将导致一些性能上的损失,即访问有层次的结构化数据的时间是O(log n),当n是数据集的大小时,对一个可伸缩的系统,最大的性能损失莫过于此。
防止软件资源用尽:用做互联网(IP)地址(互联网上的计算机地址)的数字是缺乏伸缩性的一个例子。在20世纪70年代晚期,决定用32位作为互联网地址,但在第3章将会提到,可用的互联网地址将会用尽。由于这个原因,使用128位互联网地址的新版的协议正在被采用,这就要求对许多软件组件进行修改。20要对互联网的早期设计者公平一些,这个问题是没有正确答案的,因为很难预测一个系统若干年后的需求。而且,过度考虑将来的增长可能比面临问题时再做改变的效果更糟,因为过长的互联网地址将占据额外的消息空间和计算机存储空间。
避免性能瓶颈:通常,算法应该是分散型,以避免性能瓶颈。我们用域名系统的前身来说明这一点,那时名字表被保存在一个主文件中,可被任何需要它的计算机下载。当互联网中只有几百个计算机时这是可以的,但这不久就变成了一个严重的性能和管理瓶颈。现在,域名系统将名字表分区,分散到互联网中的服务器上并采用本地管理的方式,从而解决了这个瓶颈(参见第3章和第13章)。
有些共享资源被非常频繁地访问。例如,许多用户访问同一Web页面,这会引起网络性能下降。我们将在第2章了解到缓存和复制可以用于提高频繁使用的资源的性能。
理想状态下,系统规模增加时系统和应用程序应该不需要随之改变,但这一点很难达到。规模问题是分布式系统开发中面临的主要问题,本书将深入地讨论已经成功应用的技术。它们包括复制数据的使用(见第18章)、缓存的相关技术(见第2、12章)、部署多服务器以处理经常执行的任务从而使几个类似的任务能并发地完成。
1.5.5 故障处理
计算机系统有时会出现故障。当硬件或软件发生故障时,程序可能会产生不正确的结果或者在它们完成应该进行的计算之前就停止了。第2章将讨论可能在分布式系统的进程和网络中发生的故障并对其进行分类。
分布式系统的故障是部分的,也就是说,有些组件出了故障而有些组件运行正常。因此故障的处理相当困难。本书将讨论下列处理故障的技术:
检测故障:有些故障能被检测到。例如,校验和可用于检测消息或文件中出错的数据。第2章将解释其他一些故障(例如,互联网上一台远程服务器的崩溃)是很难甚至不可能被检测到。面临的挑战是如何在有故障出现的情况下进行管理,这些故障不能被检测到但可以被猜到。
掩盖故障:有些被检测到的故障能被隐藏起来或降低它的严重程度。下面是隐藏故障的两个例子:
1)消息在不能到达时进行重传。
2)将文件数据写入两个磁盘,如果一个磁盘损坏,那么另一个磁盘的数据仍是正确的。21
降低故障严重程度的例子是丢掉被损坏的消息,这样,该消息可以被重传。读者可能意识到,隐藏故障的技术不能保证在最坏情况下有效。例如,第二个磁盘上的数据可能也坏了,或消息无论怎样重传都不能在合理的时间内到达。
容错:互联网上的大多数服务确实有可能发生故障,试图检测并隐藏在这样大的网络、这么多的组件中发生的所有故障是不太实际的。服务的客户能被设计成容错的,这通常也涉及用户要容忍错误。例如,当Web浏览器不能与Web服务器连接时,它不会让用户一直等待它与服务器建立连接,而是通知用户这个问题,让用户自由选择是否尝试稍后再连接。在下面关于冗余的段落讨论容错的服务。
故障恢复:恢复涉及软件的设计,以便在服务器崩溃后,永久数据的状态能被恢复或“回滚”。通常,在出现错误时,程序完成的计算是不完整的,被更新的永久数据(文件和其他保存在永久存储介质中的资料)可能处在不一致的状态。恢复的讲解见第17章。
冗余:利用冗余组件,服务可以实现容错。考虑下面的例子:
1)在互联网的任何两个路由器之间,至少应该存在两个不同的路由。
2)在域名系统中,每个名字表至少被复制到两个不同的服务器上。
3)数据库可以被复制到几个服务器上,以保证在任何一个服务器出现故障后数据仍是可访问的。服务器应该被设计成能检测到其他对等服务器的错误,当检测到一个服务器上有错误时,客户就被重定向到剩下的服务器上。
设计有效的技术来保证服务器上数据的副本是最新的,而且不过度地损失网络的性能,这是一个挑战。具体方法将在第18章讨论。
面对硬件故障,分布式系统提供高可用性。系统的可用性是对系统可用时间的比例的一个度量指标。当分布式系统中的一个组件出现故障时,仅仅是使用受损组件的那部分工作受到影响。如果用户正在使用的计算机出现故障,用户可以转移到另一台计算机上,并且服务器进程能在另一台计算机上启动。
1.5.6 并发性
在分布式系统中,服务和应用均提供可被客户共享的资源。因此,可能有几个客户同时试图访问一个共享资源的情况。22例如,在接近拍卖最终期限时,记录拍卖竞价的数据结构可能被非常频繁地访问。
管理共享资源的进程可以一次接收一个客户请求,但这种方法限制了吞吐量。因此,服务和应用通常允许并发地处理多个客户请求。为了详细说明这一点,假设每个资源被封装成一个对象,在并发线程中执行对资源的调用。在这种情况下,几个线程可能在一个对象内并发地执行,它们对对象的操作可能相互冲突,产生不一致的结果。例如,如果拍卖中两个并发的竞标是“Smith:$122”和“Jones:$111”,相应的操作在没有任何控制时可能是交错进行的,那么它们可能保存成“Smith:$111”和“Jones:$122”。
这个示例的寓意是:在分布式系统中,代表共享资源的任何一个对象必须负责确保它在并发环境中操作正确,这不仅适用于服务器,也适用于应用中的对象。因此,持有未打算用于分布式系统的对象实现的程序员必须做一些事情,使得对象在并发环境中能安全使用。
为了使对象在并发环境中能安全使用,它的操作必须在数据保持一致的基础上同步。这可通过标准的技术(如大多数操作系统使用的信号量)来实现。这个主题及其在分布式共享对象方面的扩展见第7章和第17章的讨论。
1.5.7 透明性
透明性被定义成对用户和应用程序员屏蔽分布式系统的组件的分离性,使系统被认为是一个整体,而不是独立组件的集合。透明性的含义对系统软件的设计有重大的影响。
ANSA参考手册[ANSA 1989]和国际标准化组织的开放分布式处理的参考模型(RM-ODP)[ISO 1992]识别出八种透明性。下面将解释最初的ANSA定义,并用范围更广的移动透明性替换迁移透明性:
- 访问透明性:用相同的操作访问本地资源和远程资源。
- 位置透明性:不需要知道资源的物理或网络位置(例如,哪个建筑物或IP地址)就能够访问它们。
- 并发透明性:几个进程能并发地使用共享资源进行操作且互不干扰。23
- 复制透明性:使用资源的多个实例提升可靠性和性能,而用户和应用程序员无须知道副本的相关信息。
- 故障透明性:屏蔽错误,不论是硬件组件故障还是软件组件故障,用户和应用程序都能够完成它们的任务。
- 移动透明性:资源和客户能够在系统内移动而不会影响用户或程序的操作。
- 性能透明性:当负载变化时,系统能被重新配置以提高性能。
- 伸缩透明性:系统和应用能够进行扩展而不改变系统结构或应用算法。
最重要的两个透明性是访问透明性和位置透明性,它们的有无对分布式资源的利用有很大影响。有时它们统一称为网络透明性。
为了说明访问透明性,我们考虑具有文件夹的图形用户界面,无论文件夹中的文件在本地还是在异地,图形用户界面应该是一样的。另一个例子是API文件,它使用相同的操作访问本地和远程文件(见第12章)。如果一个分布式系统除了用户利用ftp程序访问远程计算机上的文件之外,不允许再做这样的事,那么它就可以作为缺乏访问透明性的例子。
Web资源名或URL具有位置透明性,因为URL中识别Web服务器域名的部分指的是域中的计算机名字,而不是互联网地址。然而,URL不是移动透明的,因为某人的Web页面不能移动到另一个域中新的工作位置,因为其他页面上的所有链接仍将指向原来的页面。
通常,像URL这样的包括计算机域名的标识符妨碍了复制透明性。虽然DNS允许一个域名指向几台计算机,但它在查找名字时只选其中的一台计算机。因为复制方案通常要能够访问网络中所有参与其中的计算机,所以应该根据名字访问DNS条目中的每台计算机。
为了说明网络透明性,考虑电子邮件地址(如Fred.Flintstone@stoneit.com)的使用。该地址由用户名和域名组成。给这样的用户发送邮件不需知道他们的物理位置或网络位置,发送邮件消息的过程也不依赖于接收者的位置。因此,互联网中的电子邮件支持位置透明性和访问透明性(即网络透明性)。
故障透明性也可以用电子邮件的例子来说明,即使服务器或通信链接出现故障,最终邮件还是能被传递。24此时故障被屏蔽,因为邮件被一直重发直到它被成功传递到目的地址,即使这个过程花费了几天时间。中间件通常将网络和进程的故障转换成程序级的异常(详细解释参见第5章)。
为了说明移动透明性,再举一个移动电话的例子。假设打电话者和接电话者都在一个国家的不同地方乘火车旅行,他们从一个环境(蜂窝)移到另一个环境。我们将打电话者的电话作为客户,接电话者的电话作为一个资源。两个使用电话的用户并没有意识到电话(客户和资源)在蜂窝之间的移动。
透明性对用户和应用程序员隐藏了与手头任务无直接关系的资源,并使得这些资源能被匿名使用。例如,通常为完成任务,对相似的硬件资源的分配是可互换的——用于执行一个进程的处理器通常对用户隐藏身份并一直处于匿名状态。但正如1.3.2节指出的,情况并不总是如此。例如,旅行者每到一处便将他的笔记本电脑连接到本地网络,他应该能通过每处的不同的服务器使用本地服务(如发送邮件服务)。即使在一栋建筑物内,将要打印的文件发送到靠近用户的某台打印机上打印也是很常见的。
1.5.8 服务质量
一旦提供给用户他们要求的服务的功能,例如在一个分布式系统中的文件服务,我们就能继续探询所提供的服务质量。系统的主要的非功能特性,即影响客户和用户体验的服务质量是可靠性、安全性和性能。满足变化的系统配置和资源可用性的适应性已被公认为服务质量的一个重要方面。
可靠性和安全性问题在设计大多数计算机系统时是关键的。服务质量的性能方面源于及时性和计算吞吐量,但它已被重定义成满足及时性保证的能力。
一些应用,包括多媒体应用,处理时间关键性数据——这些数据是要求以固定速度处理或从一个进程传送到另一个进程的数据流。例如,一个电影服务可能由一个客户程序组成,该程序从一个视频服务器中检索电影并把它呈现到用户的屏幕上。该视频的连续帧在指定的时间限制内显示给用户,才算是一个满意的结果。
事实上,缩写QoS用于指系统满足这样的截止时间的能力,它的实现取决于所需要的计算和网络资源在相应时刻的可用性。这蕴含着对系统的一个需求,即系统要提供有保障的计算和通信资源,这些资源要足以使得应用能按时完成每个任务(例如,显示视频一帧的任务)。
通常今天使用的网络具有高性能——例如,BBC iPlayer通常能令人满意地播放,但当网络负载很重时,它们的性能会恶化,不能提供任何保障。除了网络之外,QoS可以应用到操作系统。每个关键性资源必须被需要QoS的应用保留,并且必须有一个提供保障的资源管理器。不能满足的资源保留请求将被拒绝。这些问题将在第20章进一步论述。