1、在许多分层协议中,每一层都有自己的报头。如果每个消息前部都只有单个报头,其中包含了所有控制信息,无疑会比使用单独的多个报头具有更高的效率。为什么不这么做?
答:协议的每一层都必须和其它层相独立。从第k+1层传送至第k层的数据同时包含了报头和数据,但是第k层协议不能对它们进行辨别。如果使用单个大的报头来包含所有信息的话将会破坏透明性,使得一个协议层的变动会影响到其它层,这显然不是我们所希望的。
2、为什么传输层通信服务常常不适于构建分布式应用程序?
答:它们通常不提供分布透明性,这意味着应用程序开发人员需要注意通信的实现,从而导致解决方案的可扩展性很差。分布式应用程序,例如基于套接字构建的分布式应用程序,将很难移植或者和其它应用程序交互。
3、一种可靠的多播服务允许发送者向一组接收者可靠地传递消息。这种服务是属于中间件层还是更低层的一部分?
答:从理论上来说,一种可靠的多播服务可以很容易的成为传输层,甚至是网络层的一部分。例如,不可靠的IP多播服务是在网络层实现的。但是,由于这些服务目前尚无法应用,它们通常使用传输层的服务来实现,传输层的服务将它们放在中间件中。如果把可扩展性加以考虑的话,只有充分考虑应用程序的需求时可靠性才能得到保证。用更高、更特殊的网络层来实现这些服务存在一个很大的争议。
4、考虑一个带有两个整型参数的过程incr。该过程将两个参数的值分别增加1.现在假定调用它时使用的两个参数是同一个变量,比如incr(i,i)。如果i的初始值是0,在执行引用调用之后i将变为什么值?如果使用复制——还原调用呢?
答:如果执行引用调用,指向i的指针被传入incr。i将会被增加两次,因此最终的结果是2。而使用复制——还原调用时,i会被两次传值,每次的初始值均为0。两次都会增加1,因此结果均为1。最后都复制到i,第二次的复制会覆盖第一次的,因此最终i的值为1,而不是2。
5、C语言中有一种称为联合(union)的构造,其中的记录(在C语言中称作结构)的字段可以用来保存几种可能值中的一个。在运行时,没有可靠的办法来分辨其中保存的是那一个值。C的这种特性是否与远程过程调用有某些相似之处?请说明理由。
答:如果运行时系统不能分辨一个字段的值类型,它就不能对该字段进行正确的封送处理。除非有一个标签字段用来清楚的表明一个字段的值类型,联合不能在远程过程调用中使用。这个标签字段不能被用户所控制。
6、处理RPC系统中参数转换的一种方法是,每台机器以自己系统使用的表示方式来发送参数,由另一方在必要的情况下进行转换。可以通过首字节中的代码来表示发送消息机器所用的系统。然而,由于要在首个字中找到开头的字节这本身也是一个问题,这种方法能行得通吗?
答:首先,当一台机器发送字节0时,消息肯定已经送到。因此目标机器可以访问字节0,而代码就在消息里面。这种方法不考虑字节是高位优先还是低位优先的字节。另一个方法是将代码放在第一个单词的所有字节中。因此不管检查的是哪一个字节,代码都能被找到。
7、假定客户通过异步RPC对服务器进行调用,随后等待服务器使用另一异步RPC返回结果。这种方法与客户端执行常规的RPC有没有什么不同?如果使用的是同步RPC而不是异步RPC,情况又如何呢?
答:二者并不相同。异步RPC向调用者返回一个通知,这意味着客户第一次调用之后,有一个额外的消息会被发送。类似地,服务端接收到它的响应消息已经发送到客户端的通知。如果保证通信可靠的话,两次异步RPC调用是一样的。
8、在DCE中,服务器在守护程序中注册自身。如果换一种方法,也可以总是为它分配一个固定的端点,然后再指向服务器地址空间中对象的引用中就可以使用该端点。这种方法的缺陷在哪里?
答:这种方法的主要缺陷是向服务器分配对象变得很难。另外,许多端点而不止一个需要被修复。如果机器中很多都是服务器,分配固定端点不是一个好办法。
9、给出一种用来让客户端绑定到暂时远程对象的对象应用的实现示例。
答:使用Java实现的类如下:
public class Object_reference {
InetAddressserver3address; // network address of object’s server
int server3endpoint; //endpoint to which server is listening
int object3identifier;// identifier for this object
URL client3code; //(remote) file containing client-side stub
byte[] init3data; //possible additional initialization data
}
Object_reference类至少需要包含对象所属的服务器的传输层地址。在具体实现中,使用了一个URL来标识包含了所有必需的客户端代码文件,用一个字节数组来保存进一步初始化后的代码。另一种实现可以直接保存客户端代码而不是一个URL。这种方法将代理对象作为引用传递,JavaRMI采用了这种做法。 10、Java和其他语言支持异常处理,当错误发生时会引发异常。如何在RPC和RMI中实现异常处理?答:由于异常通常在服务端发生,服务器存根只能捕获这个异常并把它作为一个特殊的错误响应传送给客户端。另一方面,客户存接收这个消息并抛出这个异常以保持对服务器访问的透明性。因此,接口定义语言中也需要有对异常的描述。
11、将静态和动态RPC区分开来有用吗?
答:有用。和远程对象调用有用的理由一样:它会带来更多的弹性。缺点是很多的分布透明性会被牺牲掉,其程度视哪种RPC先被使用而定。
12、某些分布式中间件系统的实现是完全基于动态方法调用的。甚至连静态的调用也被编译成动态的调用。这种方法的优点在哪里?
答:动态调用的实现能够处理所有的调用,而静态调用仅仅是其中的一种特殊情况。优点是仅仅需要实现一种机制。一个可能的缺点是性能并不是总比使用静态调用的情况要好。
13、描述一下客户端和服务器端之间使用套接字的无连接通信是如何进行的。
答:客户端和服务端都需要创建一个套接字,但是只有服务器把套接字绑定到本地的端点上。然后,服务器可以执行一个阻塞的read调用以等待从客户端发送的数据。类似地,在创建套接字之后,客户端仅仅执行一个阻塞调用以向服务端写数据。关闭连接是没有必要的。
14、说明MPI中mp_based原语和mp_isend原语之间的区别。
答:mpi_based原语使用有缓冲的通信,调用者将包含了信息的整个缓冲传送到本地的MPI运行时系统。当调用完成时,这些信息要么被已被发送,要么被拷贝到一个本地的缓冲区。如果使用mpi_isend,调用者仅仅将指向信息的指针传送给本地的MPI运行时系统,然后继续往下执行。调用者需要保证在消息被拷贝或被传送之前不能覆盖它。
15、假定只能使用暂时异步通信原语,再加上异步receive原语,如何实现用于暂时同步通信的原语?
答:考虑一个同步的send原语。一个简单的实现是使用异步通信向服务器发送一个消息,然后让调用者不停地查询接收到的来自服务器的通知或响应。另一种实现方案是,如果假设本地操作系统将接收的消息保存在一个本地缓冲区中,那么阻塞调用程序直到接收到系统的消息到达信号,之后调用程序执行异步receive。
16、假定只能使用暂时同步通信原语,如何实现用于暂时异步通信的原语?
答:异步send可以通过如下方式实现:调用者将它的消息拷贝到一个缓冲区,实际处理消息发送的进程共享该缓冲区。每当客户端将消息拷贝到缓冲区,消息发送线程被唤醒,它将该消息从缓冲区中删除并使用一个阻塞的send原语将其发送到目标机器。接收方的实现与此类似,它提供缓冲区,一个应用程序可以检查该缓冲区以确定是否有消息。
17、通过RPC实现持久化异步通信有意义吗?
答:仅仅在管理了一个队列的进程通过RPC将消息发送给下一个队列管理器时有意义。一个队列管理器为另一个管理器提供的服务是保存消息,调用的队列管理器可以获得远程队列的一个代理对象,并可能接收到每一个操作成功或失败的状态。使用这种方法时,队列管理器看到的仅仅是队列,而不会发生通信。
18、在本章中我们讲过,为了自动启动一个进程以从输入队列中获取消息,常常要使用守护程序来监视输入队列。请给出一种不使用守护程序的实现方法。
答:一个简单的实现方案是,每当接收端的进程将一条消息放进它的一个队列时,同时检查一下是否接收到了消息。
19、IBMMQSeries以及许多其他消息队列系统中的路由表是人工配置的。描述一种自动完成配置工作的简单方法。
答:最简单的是现实使用一个集中的组件,该组件维护消息队列系统的拓扑结构。它使用一种已知的路由算法来计算各个队列管理器之间的最佳路由,然后为每一个队列管理器生成路由表,这些表可以由各个管理器分别下载。这种方法适合于队列管理器相对较少但是特别分散的消息队列系统。
20、如何将持久异步通信加入到基于远程对象RMI的通信模型中去?
答:RMI应该是异步的,也就是说,在调用的时候不能即时得到调用结果。RMI应该被保存在一个特殊的服务端,它在对象服务器中的对象启动并运行时立即将RMI转发到该对象。
21、在持久通信中,接收者一般拥有自己的本地缓冲区,如果接收者不在运行状态,可以将消息放入该缓冲区中去。为了创建这种缓冲区,必须指定它们的大小。分成两方进行辩论:一方认为这种指定缓冲区大小的行为是可取的,而另一方反对这种指定大小的行为。
答:用户指定缓冲区大小使得实现更加容易。系统创建一个固定大小的缓冲区,之后缓冲区管理会十分容易。但是,如果缓冲区已满,消息可能会丢失。另一种方案是由通信系统来管理缓冲区大小,首先先制定一个默认大小,然后视情况需要扩充或者压缩缓冲区。这种方法减少了由于缺少空间而导致丢失消息的机率,但是需要系统做更多的工作。
22、请说明为什么暂时同步通信在可扩展性方面存在固有的问题,以及如何解决这些问题。
答:问题在于地理上的可扩展性受到了限制。由于同步通信需要调用者被阻塞直到消息被接收,因此,如果接收方相隔较远的话调用者可能需要阻塞很长的时间才能继续运行。解决这个问题的惟一办法是设计调用程序,使得它在发生通信时可以做其它有用的工作,以有效地实现一种异步通信。
23、给出一个将多播应用于离散数据流的例子。
答:将一个大文件传送给许多用户就是一个例子。例如,更新Web服务或软件发布的镜像站点。
24、当一组计算机组成一个逻辑上或物理上的环时,如何确保传输延迟不超过允许的最大端到端延迟时间?
答:用一个令牌在环上循环,只有当计算机获取到该令牌的时候,它才能通过环发送数据。另外,计算机持有环的时间不能超过T秒。因此,如果假设两台邻接电脑之间的通信是有限制的,那么可以得到令牌循环的最大时间,这个时间就是发送一个包的最大端到端延迟时间。
25、当一组计算机组成一个(逻辑上或物理上的)环时,如何确保传输延迟不小于允许的最小端到端延迟时间?
答:从理论上来说,接收端计算机不应该在特定的时间之前接收数据。唯一的解决方案是将数据包存储在缓冲区中,缓冲可能发生在发送端、接收端或它们之间的某一个环节。缓冲数据最好的地方是在接收端,因为这里没有不可预见的、可能延迟数据传输的障碍。接收端仅需要将数据从缓冲区中删除并将它传送至使用了一个简单的计时机制的应用程序。缺点是必须提供足够的缓冲能力。
26、想象一下,某个令牌存储桶规范说明中的最大数据单元大小是1000B,令牌存储桶速率是10MB/s,令牌存储桶的大小是1MB,而最大传输速率是50MB/s。突发的传输可以以最大传输速率持续传输多长时间?
答:令最大的突发时间间隔为Δt秒。在极端的情况下,存储桶在开始时就已经满了,还有10ΔtMB的数据在该间隔内被传进来。在突发的传输过程中,输出的数据为50ΔtMB,等于(1+10Δt)。因此,Δt等于25毫秒。
27、在这道练习题中,要求实现一个使用RPC简单客户——服务器系统。服务器提供一个名为next的过程,该过程接受一个整型数作为输入,并且返回紧接着该整型数之后的一个数。编写一个客户使用的名为next的存根,它的任务是使用UDP将参数发送给服务器,随后等待服务器响应,如果过长时间未收到响应就认为超时了。服务器过程必须在一个公开的端口监听并接受请求,完成这些请求所要求的操作,然后返回结果。
答:无。