侧边栏壁纸
博主头像
Elltor

用心发现生活,积极面对工作、事,坚持每天让自己进步一点。

  • 累计撰写 169 篇文章
  • 累计创建 1 个标签
  • 累计收到 12 条评论
标签搜索

目 录CONTENT

文章目录

《A survey of asynchronous remote procedure calls》论文翻译

Elltor
2022-05-10 / 0 评论 / 0 点赞 / 109 阅读 / 9,429 字 / 正在检测是否收录...

这篇 ACM 论文介绍了异步RPC的实现,在先在流行的RPC框架(如:Dubbo)都能看到这些技术的缩影,最经典的莫过于 Future 模式。

PDF 原文件: 链接

另外一篇经典的论文《Implementing remote procedure calls》在 ACM Digital Library 可以下载: 链接


1 介绍

远程过程调用(RPC)是分布式应用中一种简单、灵活、强大的进程间通讯(IPC)的方式[Wilbur and Bacarisse 87],它被广泛用在分布式系统和分布式应用的通讯,如Amoeba分布式操作系统、Sprite网络操作系统[Ousterhout et al. 88]、Andrew文件系统。

许多RPC系统已经在Nelson博士的理论发表后构建,其中值得注意的是Cedar RPC系统[Birrell and Nelson 84]、NCA/RPC系统[Dineen et al. 87]和HRPC系统[Bershad et al. 87]。关于这些工作的一项调查表明,然而大部分的RPC系统通常使用同步的方式,因此未能完全利用分布式应用固有的并发特性,这严重影响了各种分布式应用程序之间的交互,结果是低效的。为了实现并发人们借助其他的方式,例如轻量级进程(线程)或者低级机器间消息传递(发送|接收),如果主机的操作系统,如Unix不支持线程,将不得不使用重量级进程代替,然而这两种解决办法都不吸引用户,第一种解决方式不灵活、很难debug且在大型分布式环境中不能扩展;第二种解决方式比使用RPC系统更困难。鉴于此,许多异步RPC系统已经被设计实现以获取更高的并发性能,同时也保持了之前熟悉和简单的同步RPC。异步RPC在调用时不阻塞调用者(客户端)并且当调用者需要时可以接收回复的消息,因此期间允许客户端并行处理本地服务器调用。

这篇论文研究比较一些有特色的异步RPC系统,异步RPC系统的讨论包含:Athena Non-blocking RPC、NCA maybe RPC、Sun batching RPC、Remote Pipes、Stream(Promies)、Future 和 ASTRA。这些比较主要基于异步RPC系统的以下特点:
(1)支持接收和回复消息
(2)传输层协议
(3)调用消息和返回消息的顺序
(4)调用语义
(5)优化低延迟和高吞吐
(6)优化机器内部调用

在部分2审查了异步RPC系统的发展诱因并讨论了RPC设计准则;在第3部分展示对每一种异步RPC系统的分析结果;第4部分展示每个异步RPC系统测试得分和讨论结果。

2 背景

异步RPC机制的设计主要是为了在保持RPC抽象的简单性和熟悉性的同时实现高并行性。通过为每个RPC调用创建多个轻量级进程(线程),可以实现有限的并行度[Bal等人87]。这允许客户端对多个服务器进行多次调用,并且仍然能够与服务器并行执行。程序结构类似于fork | join,但很难调试。虽然将RPC与线程绑定会带来较少的开销,但该解决方案的可扩展性不好。在RPC调用数量动态增长和收缩的大型分布式环境中,由于线程创建、上下文切换和线程破坏的累积成本,使用线程并不经济。此外,某些主机操作系统(如Unix System V)不支持线程。

一些系统,如Multi-RPC[Satyanarayanan and Siegel 90]试图通过允许客户端同时调用一个过程的多个实例来实现更高的并行性。客户端将被阻塞,直到收到所有响应,或者客户端显式终止调用。虽然实现了一些并行性,但客户端不可能并行调用两个不同的过程。因此,在许多情况下,多RPC不能充分利用并行性。

或者可以通过使用机器间的消息传递IPC机制来实现所需的并行。然而,这样一个系统的用户必须处理许多以前隐藏在RPC中的细节,包括数据表示、消息打包,以及响应与请求消息的配对。异步RPC提供了消息传递IPC和同步RPC之间的中间抽象。

2.1 设计原则

在异步RPC系统的设计中,有几个标准是可取的。第一,异步RPC系统必须具有同步RPC系统的外观,但客户端在发出异步调用后不会等待回复。在这种情况下,客户可能无法延迟收到回复。此外,希望服务器按照客户机调用的顺序接收和执行所有调用,以保留正确的调用语义。因此,异步RPC系统应该保留传统同步RPC系统必须提供的所有优点,同时允许客户端和服务器并行执行。

第二,异步RPC系统必须设计为独立于传输,以满足不同类型的应用需求。通常,客户机和服务器涉及两种交互,间歇交换和扩展交换。所谓间歇式交换,我们指的是客户端对服务器进行几次偶尔的请求-响应(RR)类型的调用。我们对一个特定类型的服务器进行大量的数据交换。异步RPC系统应结合虚电路和数据报传输协议,以便允许应用程序选择满足其需求的最佳传输。为了获得最佳性能,可以选择虚拟电路进行扩展交换,因为它提供了更好的流量和错误控制,而处理开销可以忽略不计。另一方面,数据报由于其简单性更适合于间歇交换。

第三,必须为机器内调用优化异步RPC功能。根据Bershad等人进行的一项调查,[Bershad et al. 89]不到10%的远程活动是跨机器通话。这是因为大多数应用程序都是为了最大化本地处理而设计的。鉴于此,应该设计一个异步RPC系统,通过绕过昂贵的数据转换和网络通信操作来优化机器内调用。

3 异步RPC系统

根据调用是否返回值,异步RPC调用可以分为两种类型。大多数异步RPC系统只支持不返回值的调用,很少有系统同时支持这两个类。本文讨论的异步RPC机制的分类如图1所示。

image.png

在本节中,我们将按照开发的时间顺序检查一些异步RPC系统,并强调它们的相似性和差异。第3.1节描述了不返回值的异步RPC系统。我们将在第3.2节中讨论可以延迟接收回复的异步RPC系统。

3.1 异步RPC的返回值

3.1.1 MIT项目Athena 非阻塞RPC

麻省理工学院Athena项目[Champine et al. 90]的目标是为了教育目的整合各种计算和通信资源。Athena RPC [Souza and Miller 86]是在Athena项目的一致性模型0的约束下开发的。一些约束包括不修改Unix内核、在异构环境中支持RPC以及支持多种语言套件。它是在BSIM.2 Unix操作系统中作为原型实现的。
Athena RPC同时提供阻塞(同步)和非阻塞(异步)调用。Athena非阻塞RPC的开发主要是为了提高不需要从被调用过程返回任何信息或状态的应用程序的性能。
请求-响应(UDP-RR)协议建立在UDP之上,用于正常的阻塞RPC。非阻塞RPC使用UDP作为其传输机制。因此,它不能保证通话信息的传递,也不能保证传递顺序。因此,服务器中的执行顺序可能与客户端调用的顺序不同。
Athena 非阻塞 RPC可能具有调用语义,正如Spector的论文[Spector 85]中所定义的那样,因为不保证调用消息的传递。如果需要任何通信可靠性,应用程序必须实现自己的端到端机制,这种语义可能不适合任何事务性应用程序。
为了减少延迟,Athena非阻塞RPC在每次调用后立即发送其调用消息,此外它不会区分机器间调用和机器内调用,因此不会对本地机器内调用进行优化。

3.1.2 NCA Maybe RPC

NCA/RPC [Zahn et al. 90]由HP/Apollo开发,作为网络计算体系结构(NCA)的一部分,它为程序员提供了一组丰富的RPC调用——发送-接收的普通阻塞RPC——被称为maybe RPC、broadcast RPC的异步RPC。

要指定Maybe RPC,其接口定义语言(Interface Definition Language,IDL)文件必须在过程定义前面包含[maybe]操作属性,用下面网络接口定义语言(C语法)编写的以下代码段说明了这一点:

[maybe] void simple$op(...);

这里simple$op()是不返回值的远程过程的名称。存根生成器将生成IDL文件中指定的存根过程simple$op()。客户端可以将远程过程simple$op()作为本地过程调用。

除了上述调用类型之外,NCA/RPC还提供了在其他RPC实现中很少可用的函数,例如客户端可以发送“ping”数据包来查询未完成的请求,并发送“quit”数据包来通知服务器它将中止远程调用的处理。

NCA/RPC设计用于在无连接的传输层上工作。目前,该层支持Apollo域协议(DDS)和UDP。NCA可能RPC在特性上与Athena非阻塞RPC非常相似,两者都依赖于不可靠的数据报来传输调用消息,并且不希望服务器回复,因此它可能具有调用语义,并且消息的传递顺序无法保证。

NCA Maybe RPC不尝试缓冲调用消息,而立即发送调用消息以实现低延迟,此外它不优化机器内调用,因为它不区分机器内调用和机器间调用。

3.1.3 Sun Batching RPC

Sun ONC/RPC[Sun 88]由Sun Microsystems开发,作为开放网络计算(ONC)的一部分。Sun Batching RPC是Sun RPC提供的调用类型之一,其他的是普通的同步RPC和广播RPC。Batching RPC允许从客户端向服务器进行一系列调用,管道中的每个RPC调用都不需要服务器回复,服务器也无法发送回复消息,最后一个调用必须是正常的阻塞RPC,以便清除调用管道。
Sun RPC为应用程序程序员提供了两种类型的接口。其中一个可以作为库例程使用,另一个接口使用RPC规范语言(RPCL)和存根生成器(RPCGEN),RPCL是外部数据表示(XDR)[Sun 87]规范的扩展,要使用批处理RPC,可以使用RPCGEN或库例程。

clnt_call()库例程可用于调用Sun批处理RPC,如下所示:

clnt_call(client, PROCNUM, xdr req, &request, xdr_ret, return, timeout);

通过设置timeout、xdr_ret和无返回(NULL),该调用与正常的阻塞RPC不同。这里client是clnt_create()返回的句柄,它创建并绑定一个RPC客户端句柄,PROCNUM是要在服务器中调用的过程号,xdr req是被称为请求的数据的相应xdr例程。

Sun RPC提供UDP和TCP作为其传输通信机制,然而批处理RPC是建立在TCP之上的,与Athena 非阻塞 RPC和NCA maybe RPC相比,所有消息都是可靠传递的,TCP是唯一受支持的传输机制,这一事实使得它不适合于请求-响应类型的事务性应用程序,Sun批处理RPC的调用语义最多为一次,这是对Athena非阻塞RPC和NCA maybe RPC的可能调用语义的改进。

Sun Batching RPC利用TCP缓冲调用消息,并在一次Unix write()系统调用中将它们发送到服务器。这大大降低了系统调用开销,从而提高了性能和吞吐量。然而,在Sun批处理RPC中,没有对机器内调用进行优化。

3.1.4 远程管道

远程管道(Remote Pipe)[Gifford and Glasser 88]旨在以类型安全的方式高效传输批量数据和增量结果。这是通过一种称为信道模型的通信模型来实现的,通道模型由三个基本元素组成:远程过程、远程管道和通道组。

在信道模型中,节点类似于进程,一个节点可以包含多个通道,在这种情况下,通道要么是远程过程,要么是管道,远程过程和管道之间的区别在于前者是同步RPC,而后者是不返回值的异步RPC。一个节点可以导入任何其他节点导出的任何通道,也可以将它们重新导出到其他节点。这使得通道成为一级值,可以在节点之间自由交换[Nelson 81]。导入节点可以将通道分组为一个称为通道组的集合,频道组控制通话顺序,发送到信道组内信道的数据按发送顺序接收。

image.png

这里yyy是xxx类型的一个实例。

信道模型与传输无关,它可以通过提供自己的流控制在原始数据报之上实现,也可以在包含流控制的传输协议上实现,如VMTP[Cheriton 86]。事实上,Gifford和Glasser在TCP之上实现了它。

通道模型可以使用最多一次或恰好一次的语义来实现。然而,人们相信,由于其简单性,信道模型的大多数实现最多只具有一次语义,这与许多其他RPC系统类似,例如Sun Batching RPC。

信道模型的性能可以通过将发送给同一汇聚节点的管道调用缓冲并组合成单个消息来优化,以减少消息处理开销,从而提高吞吐量,这类似于Sun Batching RPC。其他优化包括将管道调用与过程调用相结合以清除缓冲管道调用,将管道返回组合到单个消息以减少消息处理和系统调用开销,在进程池中预分配进程以消除分叉开销,以及分解包和组以节省空间。在信道模型中,没有尝试区分机器间调用和机器内调用,因此机器内调用没有得到优化。

3.2 异步 RPC的返回值

尽管所讨论的RPC系统提供了某种形式的异步,但它们都不包括延迟接收返回结果的机制。这一缺点限制了分布式应用程序的设计,使其只能从客户端到服务器进行严格的单向交换。在这些系统中,应用程序程序员有三种选择:

1)使用同步RPC调用编程应用程序并牺牲并发性;
2)以不需要服务器回复的方式构造应用程序;
3)直接在传输层上编程。鉴于这些缺点,可以延迟接收回复的异步RPC系统,如Stream(Promises)、Future和ASTRA已经被开发出来。

3.2.1 流(Promises)

MIT Mercury系统中的Stream是第一个以干净统一的方式将同步和异步调用与返回值结合起来的RPC系统[Liskov et al 88]。Stream提供三种调用:普通同步RPC调用、Stream调用和send调用。流调用是一种带有应答消息的异步RI~调用,另一方面Send与Sun批处理RPC和远程管道调用类似,因为客户端对回复不感兴趣,除了上述三个调用之外,stream还提供了一个“flush”原语,可用于清除缓冲的调用或回复消息,以及一个“synch”原语,该原语将阻止调用方,直到所有先前调用的处理完成。

基于流的传输协议(如TCP)用于可靠地传输和排序流调用和应答消息。它简化了流的实现,并且最多提供一次调用语义。然而,流仅依赖于特定可靠的基于流的传输,这一事实使其更适合于批量数据传输,而不是低延迟调用。此外,对于请求-响应协议更合适的大多数事务性应用程序,使用TCP会导致更高的开销。
与Sun Batching RPC和远程管道一样,它的设计主要是为了实现高吞吐量,在方便的时候对调用消息进行缓冲和刷新,这是为了减少系统调用开销,虽然通过显式清除调用也可以实现低延迟,但这有点不方便。同样,没有对机器内调用进行优化。

数据流已被整合到Argus[Liskov 88]中,成为名为Promises[Liskov and Shrira 88]的新数据类型,无论何时执行流调用,都会向调用者返回一个Promise。它就像一个邮箱,保存着服务器计算的结果,当它准备好时,客户端可以声明它。声明操作的结果反映流调用的结果,如果调用成功,声明将返回结果的类型;如果调用失败,声明将返回异常的名称和类型。一个承诺可以在任何方便的顺序中多次提出,每次都会返回相同的结果。尽管只在最多一次提供调用语义,但Promises能够实现一次调用语义,因为Argus计算作为原子事务运行。

承诺的声明、流调用和接收操作如下所示:

image.png

image.png

这里x是对象类型的Promise,type是返回结果y的数据类型,当调用因异常而终止时,控件只转到except部分。

3.2.2 Future

Future[Walker et al. 90]是CRONUS系统中提供的异步RPC[Schantz et al. 86]。Future是每次客户端调用后返回的对象,它是一个欠条,可用于在稍后阶段声明调用的结果。Future由存根程序创建和声明,存根程序根据操作规范自动生成。

对于每个被调用的远程操作,存根生成器都会生成一对存根过程:FlnvokeXXX()和FCIaimXXX()。FlnvokeXXX()用于调用远程操作并返回未来,在C语言语法中,FlnvokeXXX()的调用格式如下所示:

在本例中,XXX是服务器导出的远程操作名称,object指定要操作的项,statement指定输入数据,InvokeControl用于为调用设置各种处理选项,例如服务器所在的主机名和回复到达的绝对时间限制。如果超过绝对时间限制,系统将发出错误信号。另一方面,FCIaimXXX()用于在以后声称未来。FCIaimXXX()的调用格式如下:

image.png

这里XXX是服务器导出的操作名,future是FlnvokeXXX()返回的唯一标识符,output是远程过程XXX返回的输出参数。

image.png

此外,还提供了其他三个原语来操纵未来:Discard()、IsReady()和allowMultipleClaimes()。Discard()通知系统未来不再重要,因此应该销毁;IsReady()测试未来是否已准备好收集;AllowMultipleClaimes()允许在将来声明多个回复。这是将来提供的唯一原语,用于支持具有多个应答的异步调用。
Future还提供了一个名为FutureSet的抽象。这允许将多个Future组合到一个集合中,FutureSet简化了Future的管理,消除了索赔操作的严格顺序。例如,原语FuturesetExtractReady()提取集合中已准备好的任何一个未来。随后可以使用FCIaimXXX()声明检索到的特定未来,因此FuturesetExtractReady()类似于BSD套接字[Sechrest 86]中的select()原语。

此外,Future通过一个名为漏斗的抽象来支持异步调用的流控制。漏斗基本上指定了任何时候允许的未完成Future的最大数量,当客户端调用FlnvokeXXX()时,调用将立即返回到其调用方。但是,只有在未完成Future的数量未超过最大值时,才会调用远程操作;否则,调用消息将被保留,直到未完成的Future被认领或放弃。因此通过漏斗可以防止服务器过载,但在当前的实现中,使用漏斗的流控制是在应用程序级别处理的,而不是在系统级别。

Future是在TCP和UDP上实现的。TCP是未来支持的主要传输协议。使用TCP,可以保证调用和回复消息的传递。另一方面,future不在UDP之上提供任何端到端机制,因此基于UDP的调用不可靠。虽然TCP是一种顺序传输协议,但Future不保证调用消息的传递顺序,调用消息可以在传输前的缓冲过程中重新排序[Walker 90],这是一个严重的缺点,因为服务器中的执行顺序可能与客户端调用的顺序不同。

与大多数异步RPC系统不同,Future主要针对低延迟设计的,每个请求都会立即发送调用消息,返回的结果可以按任何顺序声明,在当前的实现中,future不会忽略机器内部调用的昂贵数据转换和网络通信[Walker 90]。

3.2.3 ASTRA

ASTRA[Ananda et al. 91]是在新加坡国立大学(NUS)信息系统与计算机科学系(DISCS)的分布式计算环境SHILPA的框架内构建的。SHILPA的主要设计目标是提供一个通用的分布式计算平台,用于在异构环境中的局域网互连上构建分布式应用程序。

ASTRA调用与Stream和Future调用类似,因为它能够延迟接收结果。客户端可以使用以下原语在C语言中进行ASTRA调用:

image.png

clnthandler是rpc_clntit()返回的句柄,它创建并绑定一个客户端句柄;service是要调用的服务名称/号码;call_option参数可用于指定各种选项,例如低延迟或高吞吐量。如果调用成功,每个rpc_clntasycall()调用都会返回一个单调递增的rpcxid,如果调用出错,则返回一个-1。每个rpcxid在clnthandler中都是唯一的,用于在以后的阶段为特定调用声明回复消息。要接收clnthandler特定调用的回复,客户端可以使用以下原语:

image.png

除非clnthandler设置为NO_DELAY,否则如果此特定调用的回复消息不可用,此函数将被阻止。

除了正常的调用和声明原语外,ASTRA还提供了一个原语rpc_clntwait(),允许客户端在指定的时间限制内等待回复,还提供了其他几个原语来处理异常情况,包括rpc_clntping()、rpc_clntry()和rpc_clntabort()。rpc_clntping()原语用于确定服务器进程的状态;rpc_clntry()原语用于重新尝试特定的调用,如果之前执行过该操作,则无需重新执行该操作;rpc_clntabort()将中止服务器中挂起或执行的调用。

ASTRA是独立于传输的,因为它不依赖任何特定的通信协议。机器间调用支持两种类型的传输服务:虚电路和可靠数据报。目前支持的传输协议有:TCP/IP和RDTP/IP。RDTP是一种建立在UDP之上的可靠数据报传输协议。无论底层传输协议如何,ASTRA都能提供调用和回复消息。因此,所有调用都由服务器按照客户机调用的顺序接收和执行。此外,ASTRA旨在实现最多一次调用语义。

ASTRA将低延迟和高吞吐量通信集成到一个异步RPC模型中。用户可以明确指定调用的主要关注点是低延迟还是高吞吐量,系统将相应地优化调用。它与其他异步RPC系统(如Stream和Future)不同,后者设计为只实现其中一个,而不是同时实现两个。

与Stream和Future不同,ASTRA提供高度优化(轻量级)的机器内调用。对于机器内调用,ASTRA将绕过数据转换和网络通信,直接使用本地操作系统提供的最快的本机IPC机制,这是ASTRA提供的独特功能。然而,ASTRA并没有融合FutureSet和漏斗等概念。ASTRA中的流量控制由底层传输协议完成。

4. 异步RPC测试记录

下表是所讨论的异步RPC系统的测试记录。这里定义的调用语义与Spector的论文[Spector 82]中的定义非常相似,只是我们将Only-one-Type-1表示为至多一次。

表 1 不同异步RPC的比较

5. Conclusion

本文简要分析了为什么异步RPC是在异构分布式计算环境中实现更高并行性的最合适范例。还讨论了这种机构的设计准则。最后,对近年来发展起来的一些异步RPC系统进行了分析和比较。

这项调查揭示了几个要点。首先,目前的趋势是开发具有返回值的异步RPC系统。最新的异步RPC开发(如Stream、Future和ASTRA)都属于这一类,这一点很明显。其次,这里调查的大多数系统没有针对机器内调用进行优化。一个可能的原因是,直到最近Bershad等人报告了他们的发现[Bershad et al. 89],才知道机器内调用的主导地位。最后,虚电路(TCP)是异步RPC系统的一种流行传输机制,因为它方便地提供了异步RPC调用的可靠性和顺序。

虽然强调了异步RPC的重要性,但我们预计正常的同步RPC调用将占主导地位,几乎所有的异步RPC系统都有一个同步的对应系统,这证明了我们的观点,我们相信未来的RPC实现将集成同步和异步调用,以提供统一、完整和全面的远程操作机制,只有这样,分布式应用程序才能得到普遍和简单的支持。

0

评论区