目录:绪论,通信,进程,命名,同步,一致性和复制,容错性,安全性
第2章 通信
分布式系统中的通信都是基于底层网络提供的底层消息传递机制的,通过消息传递来描述通信过程比使用基于共享存储器的原语来描述更困难。
2.1 分层协议
要实现两个机器上进程间的消息传递,必须在不同层次上制定多种协定,包括从位传输的低层细节到信息表示的高层细节在内的各层。
国际标准化组织(ISO)颁布了OSI模型,标注了通信涉及的各个层次以及各层执行的特定任务。OSI模型是用来支持开放式系统间的通信的。将规定了各系统间通信方式的规则归纳形成协议。为了使一组计算机能够通过网络相互通信,它们必须使用相同的协议。
协议可以分为两大类:①面向连接的协议。消息发送者和接收者必须首先显式地确立连接,然后进行数据交换,通信完毕后必须释放连接。②无连接协议。交换数据之前不需要建立连接,消息发送者只需要在准备好的时候开始传送第一个消息即可。
OSI模型的通信过程分为7层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
消息发送者从应用层开始逐层添加一个报头或报尾,并向下层传递,通过最底层的物理层执行传输任务;消息接收者收到消息后从物理层开始逐层对该层原来加上的报头进行检验,并将其去掉后向上层传递,最终抵达应用层。
分层协议的可贵之处在于它带来的独立性,即每一层都有自己的协议,可以单独改变某一层的协议,而不会对另一层造成影响。
1. 底层协议:物理层、数据链路层、网络层
物理层负责为接口制定电气、机械和信号方面的标准,以确保某台机器发送的0信号在接收机器上仍然被识别为0信号,而不会变成1信号。
数据链路层负责实现通信网络中的错误检测和纠正机制,该层将若干位组成一个被称作帧的单元,并检查每一帧是否被接收者正确接收。数据链路层在每一帧的开头和结尾分别放置特殊的位模式来对头尾作出标记,并且用某种方法将帧中所有的字节相加,计算出校验和,接收者对校验和进行验证。
网络层的主要任务是在消息从发送者传送至接收者的过程中,选择最佳的转发路径,即路由选择(routing)。评价指标是所选择路径的传输延迟时间,这与各条线路上的网络通信流量以及排队等候发送的消息数量有关。目前应用最广泛的网络协议是无连接的网际协议(IP),一种日趋流行的面向连接的协议是ATM网络中的虚拟信道(virtual channel),可以将一组虚拟信道组合成一条所谓的虚拟路径,而不需要在两台主机之间单独建立每个虚拟信道。
2. 传输协议
传输层的任务是提供可靠的连接服务。无论是建立在面向连接的网络层服务之上还是无连接的网络服务之上,传输层中的软件负责将所有的包依照原来的顺序排列好。
Internet的传输协议称为传输控制协议(transmission control protocol,TCP),Internet协议组也支持无连接的传输协议,该协议称为通用数据协议(universal datagram protocol,UDP)。TCP的优点在于它可以在任何网络上可靠工作,明显缺点在于引入的开销显著增加。当性能与可靠性的要求发生冲突时,可以考虑的另一种方案是采用UDP,并且辅之以针对特定应用程序进行了优化的附加错误控制及流程控制手段。
3. 高层协议:会话层与表示层协议、应用层协议、中间件协议
会话层本质上是传输层的增强版本,它提供用于追踪正在谈话的一方的对话控制,提供同步功能,这对于长时间的传输过程非常有用,它允许用户在传输过程中插入若干检查点,这样如果传输崩溃,只需要回退到最近的一个检查点,而不需要从头开始重新传输。
表示层考虑低层传输未所表示的意义,即多数消息并不是由随机的位串组成的,而是由更结构化的信息,比如人名、地址、金额等组成。
应用层通常为针对某个特定的应用程序制定协议,例如Internet的文件传输协议(file transfer protocol,FTP)和超文本传输协议(hypertext transfer protocol,HTTP)。
中间件是一种应用程序,它在逻辑上位于应用层,但在其中包含有多种通信协议,这些协议代表各自所在的层,独立于其他更加特别的应用。因此,在高层通信协议和用于建立各种中间件服务的协议间作出区分。
有多种协议可以对各种中间件服务提供支持,例如身份验证协议、授权协议、多种分布式提交协议、分布式锁定协议。中间件通信协议支持高层通信服务。
2.2 远程过程调用
为了使分布式系统中消息传递过程隐藏在不同机器间的通信,Birrell和Nelson等人提出一套远程过程调用(remote procedure call, RPC)方法,认为应该允许程序调用位于其他机器上的进程。当机器A上的进程调用机器B上的进程时,A上的调用进程被挂起,而B上的被调用进程开始执行,调用方可以通过使用参数将消息传递给被调用方,然后可以通过传回的结果得到信息,编程人员看不到任何消息传递过程。
存在问题:①在不同的地址空间执行,具有复杂性;②参数和结果的传递过程具有复杂性;③潜在的故障引发问题。
1. 本地调用过程
主程序作为调用方调用进程,调用方首先把参数反序压入堆栈,进程操作运行完毕后,将返回值放在某个寄存器中,将控制权交回调用方,调用方随后将参数从堆栈移出,使堆栈还原到初始状态。
三种参数传递方式:传值调用(call-by-value)、引用调用(call-by-reference)、复制-还原调用(call-by-copy/restore)。
2. RPC操作过程
RPC的思想是尽量使远程调用具有与本地调用相同的形式。包括以下步骤
(1)客户过程以正常的方式调用客户存根;
(2)客户存根生成一个消息,然后调用本地操作系统;
(3)客户端操作系统将消息发送给远程操作系统;
(4)远程操作系统将消息交给服务器存根;
(5)服务器存根将参数提取出来,然后调用服务器进程;
(6)服务器进程执行要求的操作,操作完成后将结果返回给服务器存根;
(7)服务器存根将结果打包成一个消息,然后调用服务器操作系统;
(8)服务器操作系统将含有结果的消息发送回客户端操作系统;
(9)客户端操作系统将消息交给客户存根;
(10)客户存根将结果从消息中提取出来,返回给调用它的客户过程。
该过程将客户过程对客户存根发出的本地调用转换成对服务器过程的本地调用,而客户和服务器都不会意识到有中间步骤的存在。
3. 参数传递
(1)传递值参数:简单的将参数打包进消息中(参数编组)通过网络发送消息至服务器。需要解决不同机器对数字、字符以及其他种类的数据项的表示方式不同和字节排列次序不同造成的问题。
(2)传递引用参数:指针如何传递?指针只在使用该指针的进程所在的地址空间才有意义。第一种方法是完全禁止使用指针和引用,该方法极为不可取。第二种方法是将指针地址内的内容复制到消息中,发送给服务器,当服务器完成操作后,将原先的消息送回客户存根,客户存根将它们复制回客户进程。如果存根知道缓冲区对服务器来说是输入参数还是输出参数,就可以省略其中的一个复制步骤。问题是,只能处理指向简单数组和结构的指针,无法处理一般意义上的指针,即指向任意数据结构。
(3)参数说明和存根生成:调用者和被调用者就互相交换的消息格式达成一致,并且在进行诸如传递复杂数据结构之类的操作时遵循相同的步骤,即双发遵循相同的协议,包括对消息格式的规定、对编码规则的规定、对实际交换方式的规定。在完整的定义了RPC协议之后,需要实现客户存根和服务器存根,幸运的是,相同协议所使用的存根在用于不同的进程时,仅仅是面向应用程序接口的不同,接口通常使用接口定义语言(interface definition language,IDL)来说明。
4. 扩展的RPC模型
(1)门(door):一个与PRC等价的机制,用于在同一台机器的不同进程间通信。在使用时,服务器进程对门进行注册,获得一个标识符,给该门取名与标识符关联,随后其他进程通过名字调用该门。
(2)异步RPC:在常规RPC中,当客户调用远程进程时会阻塞等待;在异步RPC中,服务器正在接收到RPC请求后立即向客户送回应答,之后再调用客户请求的过程,客户接收到服务器的确认后,将不再阻塞,而是继续向下执行。当服务器进程执行完毕后,对客户进行调用,中断客户程序,然后将结果返回给用户。
(3)异步RPC的变异形式:客户向服务器发送请求后立即继续执行其他程序,即客户不等待服务器返回接收请求的确认,称为单向RPC(one-way RPC)。这种方式的问题是,如果无法确保可靠性,客户就无法确定它发出的请求是否能够得到处理。
5. 实例:DCE RPC
(1)DCE的介绍:DCE是分布式计算系统(distributed computing environment,DCE),是设计用来作为在现有的(网络)操作系统与分布式应用程序之间的中间抽象层执行的。DCE的主要思想是,使用者可以在现有的一组机器上安装DCE软件,然后就可以运行分布式应用程序,而不会对现有的(非分布式)应用程序造成影响。所有DCE的底层编程模型都是客户-服务器模型。DCE本身的一部分是由多个服务构成的,包括分布式文件服务,目录服务,安全服务,分布式时间服务等。
(2)DCE RPC的目标:RPC系统使客户可以通过简单的本地过程调用来访问远程服务。RPC系统负责向客户隐藏所有细节,负责自动找到恰当的服务器,建立通信(称为绑定binding),还能处理双向数据传输,自动完成数据类型的转换。优点是:具有隐藏细节的能力,使客户和服务器高度独立,可以分别采用不同的高级语言编写程序,运行于不同的硬件平台和操作系统之上,支持非常多的网络协议和数据表示方式,而不需要客户和服务器进行任何干预。
(3)客户程序和服务器程序的编写:首先需要调用uuidgen程序,要求该程序生成一个原型IDL文件。IDL文件是由接口定义语言IDL描述的接口定义,其中包括一个接口标识符。下一步是编辑IDL文件,填入远程过程名以及它们使用的参数。IDL文件编写完毕之后,可以调用IDL编译器来编译它,输出头文件、客户存根、服务器存根。接下来,由应用程序编写人员编写客户和服务器代码,调用头文件,对双方的存根进行编译,然后将得到的客户代码和客户存根的目标文件与运行时库连接起来,得到客户程序的二进制可执行形式。
(4)将客户绑定到服务器:第一步,定位服务器所在的机器;第二步,定位该机器上的服务器进程。服务器机器由网络地址和服务器名标识,服务器进程由端口(port)识别。服务器进程需向该机器上的DCE守护程序(DCE daemon)注册端点,每一台运行服务器的机器上都由DCE守护程序维护一张(服务器,端点)对列表。服务器进程通过目录服务,向目录服务器注册网络地址。客户机器通过目录服务器查找服务器地址,通过该地址下的DCE守护程序查询端点,最后执行RPC。
(5)执行RPC:略
2.3 远程对象调用
对象最重要的特征之一就是通过定义良好的接口向外界隐藏其内部结构,即实现对数据的封装。被封装的数据称作状态(state),对这些数据的操作称作方法(method),只有通过接口(interface)才能使用方法。一个对象可以实现多个接口,在给定一个接口定义的情况下,也可以有若干个对象提供接口的实现。
1. 分布式对象
(1)定义:将接口放在一台机器上,让对象本身驻留在另一台机器上,这种组织结构通常称为分布式对象(distributed object)。
(2)代理:是对分布式对象接口的实现。当一个客户绑定到一个分布式对象的时候,该代理(proxy)被加载到客户的地址空间中。代理唯一的工作是将对方法的调用编组成消息,并且对应答消息进行解编,将调用的方法得到的结果放回给客户。
(3)编译时对象:类的实例,对象形式直接与语言级对象相关联。比如在Java中,可以通过定义类及该类实现的接口来完整的定义一个对象。编译时对象的一个缺陷是对特定编程语言的依赖性,除了在编译时生成对象外,另一种构建分布式对象的方法是在运行时显式生成对象。
(4)运行时对象:实际对象的实现方法多种多样,例如开发人员用C语言编写的一个库,包含多个函数,可以将其封装,使其表现为一个对象,以便从远程机器调用库中的方法。一种常用的方案是使用对象适配器。
(5)持久对象:不依赖于当前的服务器,当前管理持久对象的服务器在退出运行之前,可以先把持久对象的状态存储到辅助存储器上,之后新启动的服务器可以由存储器将对象的状态读到自己的地址空间中,对调用请求进行处理。
(6)暂时对象:只在管理该对象的服务器存在的期间存在,服务器退出运行后,该对象也就不再存在。
2. 将客户绑定到对象
支持分布式对象的系统一般都提供系统范围内的对象引用(可以作为方法调用的参数),可以在位于不同机器上的进程之间自由传递。
如果进程获得了某个对象的引用,那么在调用该对象的方法前必须首先绑定到该对象。
绑定将产生一个位于该进程地址空间内的代理,它实现了包含有此进程所能调用的方法的接口。给底层系统一个对象引用,它自动的通过某种途径来定位管理该实际对象的服务器,随后将代理放置在客户地址空间中。
隐式绑定允许客户在只使用对象引用的情况下直接进行方法调用,可以在引用被连接到实际对象上的时候将客户透明的绑定到对象上。
显示绑定时,客户必须首先调用某个特殊函数来绑定到对象上,随后才能调用该对象的方法。
3. 对象引用的实现
对象引用必须包含足够的信息,客户才可以绑定到服务器上。
一个简单的对象引用包含实际对象驻留的机器的网络地址,进程端点,和对象的标号。
为了避免服务器机器崩溃导致端点失效,在每台机器上驻留一个本地守护程序,监听某个公开的端点,并且通过端点表来追踪服务器与端点的对应关系。
为了实现在不破坏对象引用的前提下,将服务器移到另一台机器上去,不能将机器的网络地址编码进对象引用中,一种解决方法是使用定位服务器来追踪管理对象的无服务其当前在哪一台机器上运行。
4. 静态进程方法调用与动态远程方法调用
将客户绑定到对象之后,就可以通过代理来调用对象的方法,这种远程方法调用(remote method invocation)称为RMI。
(1)静态调用:使用诸如Java之类的基于对象的语言来自动生成存根,调用预先确定的接口定义的方法。静态调用要求在开发客户应用程序的时候就已知对象接口,如果接口发生变化,就必须重新编译客户应用程序,然后才能使用新的接口。
fobject.append(int)
(2)动态调用:在运行时建立方法调用,使用动态调用的应用程序直到运行时才对需要在远程对象上调用的方法做出选择。
invoke(fobject, id(append), int)
其中操作id(append)返回方法append的标识符。
5. 参数传递
可以使用对象引用作为方法调用的参数,在使用对象引用作为参数来进行方法调用时,若该引用指向远程对象,则通过引用来传递,如果引用指向的是本地对象,则采用值传递。
将对象引用作为参数来进行方法调用的做法可能需要复制整个对象,无法对这种情况进行隐藏,所以被迫显式地区分本地对象和分布式对象,损害了分布透明性。
6. 实例1:DCE远程对象
DCE分布式对象表现为远程对象的形式,其实际的实现驻留在服务器上,服务器负责在本地创建C++对象,并且将方法向远程客户所在的机器公开。
两类分布式对象:(1)分布式动态对象,由服务器以客户的名义在本地创建,原则上只能由所代表的客户访问,客户向服务器发出请求,然后服务器创建对象。(2)分布式命名对象,由服务器创建后不仅仅与一个客户相关联,而是供多个客户共用,命名对象在目录服务器中注册,客户查找到该对象后绑定到该对象上。
DCE中每个远程对象调用都是通过RPC的方式进行的,服务器维护一个对象列表,记录了对象的标识符及接口的标识符,客户以参数传递的方式向服务器发送方法调用的请求,服务器使用参数来分派所请求的方法。
DCE提供了将对象放置在辅助存储器上的能力,以代替将所有对象都保持在主存储器中的做法。调用不在对象列表中的对象时,系统调用针对特定服务的查询函数来将对象由辅助存储器取出。
7. 实例2:Java RMI
Java也采用远程对象作为分布式对象的唯一形式。
远程对象与Benin对象的差异:(1)对象复制不同,本地对象复制可以得到与被复制对象完全相同的拷贝,而复制远程对象时,不仅要复制实际对象,还要复制当前绑定到该远程对象上的每个客户所使用的代理,如果远程客户想要访问服务器上的对象拷贝,就必须首先重新绑定到该对象上。(2)对象阻塞不同,本地对象的阻塞通过声明为synchronized方法,当两个进程同时调用该方法时,其中一个执行另一个阻塞;远程对象的阻塞是在客户端存根(代理)中进行阻塞,或者是只在服务器上进行阻塞,需要相对更为复杂的协议。
Java RMI在调用远程对象时,本质上是通过代理实现了对远程对象的引用。远程对象由两个不同的类创建,一个类包含有服务器端代码的实现,称为服务器类,包含对象状态的描述以及操纵这些状态的方法的实现;另一个类包含有客户代码的实现,称作客户类,包含代理的实现。代理拥有让客户调用远程对象的方法所需的全部信息,可以把代理作为对远程对象的引用来使用。
这种引用远程对象额方法灵活性很强,特别是它允许采用针对特定对象的解决方法。例如,考虑一个状态在一段短时间内只会变化一次的远程对象,我们可以将该对象的全部状态在绑定时复制给客户,每一次客户需要调用方法的时候,它都对本地拷贝进行引用,为了确保一致性,每一次调用时还要检查服务器的状态是否发生了变化,如果是的话就要对本地拷贝进行更新。
2.4 面向消息的通信
远程过程调用和远程对象调用都有助于隐藏分布式系统中的通信,增强了访问透明性。但是在无法保证发出请求时接收端正在运行,而且其同步特性会造成客户在发出的请求得到处理之前被阻塞,从而造成资源的浪费。采用消息传递机制可以解决上述问题。
1. 通信中的持久性和同步性
(1)通信系统的组织结构:应用程序在主机上执行,主机向通信系统提供接口,通过接口提交待传输的消息,主机之间通过由通信服务器组成的网络相连,通信服务器在主机间传递消息。
(2)电子邮件系统的通信过程:用户代理将消息提交给主机,主机将消息发送给本地邮件服务器,在其输出缓冲区暂存,后转发至目标邮件服务器并在其缓冲区暂存,接收主机的接收者用户代理接收消息至本地缓冲区中。
(3)持久通信:需要传输的消息在提交之后由通信系统来存储,直到将其交付给接收者为止,发送消息消息的用用程序不必在提交消息后保持运行,接收消息的应用程序在消息提交时也可以不处于运行状态。
(4)暂时通信:通信系统只在发送和接收消息的应用程序的运行期间存储消息,如果通信服务器无法将消息递送到下一服务器或接收者,消息将被简单地丢弃。
(5)异步通信:典型特征在于发送者把要传输的消息提交之后立即继续执行其他程序,意味着消息存储在位于发送端主机的本地缓冲区中,或者存储在送达的第一个通信服务器上的缓冲区中。
(6)同步通信:发送者在提交消息之后会被阻塞,直到消息已经到达并被存储在接收主机的本地缓冲区中以后,也就是消息确实已经传送到接收者之后,才会继续执行其他程序。
(7)通信类型的组合形式:持久异步通信、持久同步通信、暂时异步通信、暂时同步通信。
(8)暂时同步通信的不同形式:(基于消息接收的)消息送达接收主机的缓冲区后解除发送者的阻塞;(基于交付的)消息送达接收者以开始进一步处理时解除发送者阻塞;(基于响应的)消息在接收者处理完成后解除发送者阻塞。
2. 面向消息的暂时通信
(1)Berkeley套接字:套接字接口(socket interface)提供了一个对接传输层接口的原语集。应用程序把要发送的数据写入套接字,接收方应用程序从套接字中读出数据。对应于每一种特定的传输层协议,本地操作系统都要使用一个实际的通信端点,而套接字形成了位于实际通信端点之上的一个抽象层。
(2)用于TCP协议的套接字原语:socket创建新的通信端点;bind将本地地址与新创建的套接字相关联;listen用于服务器为用户调用预留资源,宣布已经准备好接受连接;accept阻塞服务器直到有连接请求为止;connect要求调用者制定一个传输层地址发出连接请求,调用后阻塞直到成功连接;write用于发送数据;read用于接收数据;close关闭连接。
(3)消息传递接口(MPI):是一个应对程序的硬件独立性需求而出台的消息传递标准,简称消息传递接口(message-passing interface,MPI)。MPI是为并行应用程序设计的,因而是为暂时通信量身定做的。MPI假定通信在一个已知进程组内发生,每个组配有一个标识符(ID),组内每个进程也分配一个局部标识符(ID),即(组ID,进程ID)就可以唯一确定消息的来源或目的地。
(4)MPI的消息传递原语:MPI_bsend将要发送的消息追加至本地发送缓冲区;MPI_send发送消息至本地或远程缓冲区;MPI_ssend发送消息直到对方接收;MPI_sendrecv发送消息直到接收到应答消息;MPI_isend异步传递消息的引用;MPI_issend传递消息的引用直到对方开始接收;MPI_recv阻塞等待接收消息;MPI_irecv异步接收消息。
3. 面向消息的持久通信
提供持久异步通信的面向消息中间件服务一般称为消息队列系统(message-queuing system)或者面向消息的中间件(message-oriented middleware,MOM)。
这类系统的本质是,提供消息的中介存储能力,从而不需要消息发送者和接收者在消息传输过程中都保持激活状态。
消息队列系统的设计目标一般是用于支持那些时间要求较为宽松的消息传输。
(1)消息队列模型:基本思想是应用程序通过在特定队列中插入和读取消息来进行通信。即使在消息发送过程中接收者的及其未处于运行状态,消息也能送到。重要特征之一是,通常只能确保发送者发出的消息最终能够插入到接收者的队列中,并不保证消息到达的时间,甚至不能保证消息一定会得到读取,消息的读取由接收者来决定。
(2)消息队列系统的一般体系结构:源队列,发送者的本地队列;目的队列,消息要传输到的目的队列;全部队列的集合分布在多台机器上,需要维护一个由队列到其所在网络位置之间的映射关系;队列管理器,直接与应用程序交互,负责将输入的消息转发给其他的队列管理器;中继器一般有助于构建可扩展的消息队列系统,允许对消息进行二次处理,例如日志记录等,可以将消息转换成接收者能够理解的格式,还可以用于多播的目的;路由器,使用若干了解网络拓扑的路由器可以解决消息队列系统中对队列-位置映射进行动态维护的问题。
(3)消息转换器:为了实现不同消息格式的应用程序间的通信,同时又实现灵活的扩展,一般的方法是提供几种共存的不同格式,通过消息转换器实现各种格式之间的转换。其主要目的是将输入消息的格式转换为目的应用程序能够理解的格式。消息转换器的核心是一个数据库,数据库中的规则规定了如何将格式为X的消息转换为格式为Y的消息,问题在于如何定义这些规则。
(4)消息队列系统的服务要求:持久异步通信,可靠的消息传递,消息的优先级、日志功能、高效的多播、负载平衡、容错性等。
4. 示例:IBM MQSeries
MQSeries系统是一种消息队列系统,流行于IBM主机的传统领域。IBM主机主要是用来访问和操纵大规模数据库的。
(1)概述:所有队列由队列管理器管理,队列管理器负责从其发送队列取出消息,然后转发给其他队列管理器,同时还负责从底层网络获取输入的消息并进行处理,随后将消息放入恰当的输入队列。一对队列管理器通过消息通道相连,消息通道是传输层连接的抽象,是在发送者队列管理器和接收者队列管理器之间单向的可靠连接,队列中的消息通过该通道传输,消息通道的两端各自由一个MCA(message channel agent,消息通道代理)来管理。队列管理器可以连接到其管理的队列所属的应用程序所在的进程中去,应用程序通过接口对队列进行操纵,当队列管理器与应用程序位于不同的机器上时,访问队列管理器的接口作为代理实现,使用基于RPC的传统同步通信来与队列管理器通信。
(2)通道:每个消息通道都拥有且只有一个与其相对应的发送队列,它从中取出消息,传输给另一端。只有在通道两端的MCA都已启动运行的情况下,消息才能沿通道进行传输。启动方法包括,①手动启动两端的MCA;②由应用程序通过激活发送端或者接收端MCA来直接启动通道的一端;③对通道的发送队列进行配置,使其在第一个消息放入队列时触发一个触发器,该触发器随之启动与其相关联的一个处理程序,该处理程序负责启动发送端MCA;④通过网络来启动MCA,特别是,如果通道一端已经激活,它就可以发送一条控制消息,请求另一端的MCA启动。每一个MCA都有一组相关的属性(包括传输类型、先入先出要求、消息长度、建立连接的重试次数、消息支付重试次数等),发送端MCA与接收端MCA的属性值应该是一致的,并且应该在建立通道之前就协商好。
(3)消息传输:MQSeries中的目的地址由两部分构成,第一个部分包含将要接收消息的队列管理器的名字,第二部分是目的队列的名字,队列管理器将要把消息添加到该队列中去。还必须指定消息传输的路由,通过给出其本地发送队列的名字来实现,不必在消息中包含完整的路由,路由被存储在队列管理器中的路由表中。消息在传输过程中可能需要经过多个队列管理器才能到达目的地,当消息被中途遇到的队列管理器收到时,该队列管理器简单地从消息报头中提取出目的队列管理器的名字,随后在路由表中进行查询,以决定要将该消息放入哪一个本地发送队列中去。为了避免替换队列管理器或更改队列管理器的标识符而影响所有应用程序,中继队列管理器通常为队列管理器取一个本地别名,如果某队列管理器的名字改变了,就需要改变它在其他所有队列管理器中的名字,但不会对应用程序造成影响。
2.5 面向流的通信
之前的通信都是对某种程度上独立且完整的信息单元进行交换,这种类型通信的典型特征是,它并不在乎通信究竟在哪个确切时间发生,同步对通信的正确性没有影响。然而,在某些形式的通信中,同步扮演了关键的角色,分布式系统需要提供一些功能来为时间敏感的信息交换(比如音视频流和视频流)提供支持。
1. 为连续媒体提供支持
(1)媒体:媒体是指传送信息额手段,包括存储介质、传输介质、显示媒介等。媒体的类型是指信息的表示方式,即信息在计算机系统中的编码方式。
(2)连续媒体:不同数据项之间在时间上的联系对正确解释数据含义非常重要。
(3)离散媒体:数据项之间的时间联系对于正确解释数据含义并不重要。
(4)数据流:数据流是数据单元的序列,可以应用于离散的媒体,也可以应用于连续媒体。例如UNIX中的管道或者TCP/IP连接就是面向字节的离散数据流,播放音频文件时一般要求在文件与音频设备之间建立连续数据流。
(5)离散数据流:在异步传输模式下,流中的数据项是逐个传输的,但是对某一项在何时进行传输并没有进一步的限制,这是采用离散数据流时常见的情况。
(5)连续数据流:同步非常关键。在同步传输模式下,数据流中每一个单元都定义了一个端到端最大延迟时间,数据单元是否远小于最大允许延迟并不重要。在等时传输模式下,数据单元必须按时传输,也就是数据传输的端到端延迟时间必须同时受到上限和下限的约束。
(6)复杂流:简单流只包含有单个数据序列,而复杂流由若干相关的简单流——子流构成。复杂流中各子流之间的关系常常是时间敏感的。子流必须是始终保持同步,来自多个流的数据单元都必须成对传输。
(7)信源和信宿:流一般可以看做信源和信宿之间的虚拟连接,信源或信宿可以是进程,也可以是设备。可以由单个的信源和信宿,也可以建立多方通信,最常见的多方通信情况是将多个信宿连接到单个流上,这时数据流是对若干接收者进行多播。
(8)流质量和过滤器:如果接收者对流的质量提出不同的要求,过滤器能够将输入流调整为各种不同质量的输出流。
2. 流与服务质量
时间敏感的需求一般统称为服务质量(quality of service,QoS)需求。这种需求描述了底层分布式系统及网络在确保传输质量方面的需求。连接数据的QoS主要涉及时间、容量以及可靠性。
(1)描述QoS:可以通过提供精确的流规格说明来表达QoS需求,其中指定要求的带宽、传输速率、延迟等。在Partridge开发模型中,通过令牌存储桶算法的方式来表述流的特征。令牌存储桶算法的基本思想是以恒定的速率来产生令牌,米格令牌代表允许应用程序向网络传递的固定数量的字节。令牌在存储桶中进行缓冲存储,存储桶容量有限,当它装满之后就开始丢弃令牌。令牌存储桶算法所要达成的目的在于用相对恒定的速率向网络传输数据,传输速率由令牌产生的速率决定。在流规格说明中,应用程序必须保证将依照令牌存储桶算法的输出结果来向通信系统送出数据单元。
(2)建立流:一旦以流规格说明之类的方式对数据流进行了描述,分布式系统就可以为流的建立以及满足其在QoS方面的需求而分配资源了。与流管理相关的资源主要包括带宽、缓冲区以及处理能力等。RSVP(resource reservation protocol,资源保留协议)是一种传输层控制协议,它用于在网络路由器上保留资源。RSVP是一种由接收者启动的QoS协议,要求接收者沿传输路径想发送者发送保留资源的请求。资源保留高度依赖于数据链路层,ATM网络就是提供了自己一套参数的数据链路层网络。
3. 流同步
(1)主要问题:在流之间保持时间上的关联。
(2)两种类型:离散数据流与连续数据流之间保持同步,连续数据流之间保持同步。
(3)流同步原理:同步是在建立流的数据单元这个层次上的,也就是说,只要让两个流的数据单元保持同步,就可以让两个流同步。
(4)同步机制:存在一个专门在少数几个简单流上执行读写操作的进程,该进程确保这些操作遵守指定的时间及同步约束条件。缺点是,完全由应用程序来负责实现同步,但它只有低层功能可用。更好的做法是,想应用程序提供接口,允许它更方便地对流和设备进行控制。
(5)同步机制的分布性:首先,由请求同步对的子流组成的复杂流的接收端需要了解同步究竟要达到哪些要求,也就是说,它必须使完整的同步规格说明在本地可用。在实践中一般是隐式地将不同流多路复用到包含所有数据单元的单个流中。
(6)应该选择在发送端还是接收端进行同步:由于每个子流的延迟可能不同,在接收端做到同步是非常困难的。更好的做法是在发送端将两个子流合并起来,得到的流中数据单元是由成对的样本构成的,分别来自两个子流的样本组成一对,这样接收者只要读取数据单元并将它分离成两个子流的样本就行了,这种情况下,能够保证两个子流的延迟相同。
网友评论