NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

分布式计算编程模型之 RPC

  • 2016-04-28
  • 本文字数:3699 字

    阅读完需:约 12 分钟

远程过程调用(RPC)范式的出现可以追溯到 40 年之前。时至今日,它仍是在编写分布式应用时使用率最高的一种编程模型。只是近些年来,人们对于 RPC 技术的质疑与批评声逐渐多了起来。Steve Vinoski 在 2008 年曾尖锐地指出,之所以 RPC 仍然能够得到诸多开发者的支持,其原因只有一个:舒适感!Vinoski 完全不认可这种思想,他表示:

“开发者的舒适感真的比正确性、可伸缩性、性能、关注分离、可扩展性以及附加的复杂性还要重要吗?”

尽管面临着这些尖锐的批评,但 RPC 的历史地位是不容置疑的,而它在现代化的应用中仍能够占据一席之地,成为分布式计算中一种重要的编程模型。正在攻读博士学位的 Christopher Meiklejohn 近来开设了一系列博客文章以回顾分布式计算中的各种编程模型与语言,在其中一篇文章中对 RPC 进行了详尽的回顾与展望。

概述

简单来说,一台机器上的程序对另一台机器上的子程序的调用就是一次 RPC 调用。在调用过程中,主程序不需要操心与远程执行相关的任何代码,与本地调用相比,其唯一区别就在于需要提供远程节点的标识。最早为人所知并接受的 RPC 实现是由 Sun 提供的 SunRPC 机制,使用在其网络文件系统(NFS)中。

除此之外,常见的 RPC 机制还包括 Java 的 RMI、DCOM、XML-RPC、SOAP、CORBA,以及 Google 的 gRPC 等等。

RPC 的早期发展

RPC 思想最早的原型可追溯至 1974 年所发布的 RFC 674 草案 —— “过程调用协议文档第 2 版”,该草案当时的目标是为因特网上的全部 70 个节点定义一种共享资源的通用方式,在该草案中引入了过程调用范围第 2 版(PCP)的概念。而在第二年发布的 RFC 684 草案 —— “对以过程调用作为网络协议的评论”中,首次分析了 RPC 这种编程范式存在的三大问题以及这些问题与分布式系统的本质问题之间的关联。这三大问题可以简要地概述如下:

  • 过程调用通常是一种命令式操作,而命令式操作通常是一种来自底层抽象的非常快速的上下文切换操作。
  • 本地调用与远程调用的不同之处在于:远程调用可能会产生延迟,甚至在产生故障时可能永远也不会返回.
  • 异步的消息传递,或是发送某个消息并等待响应是一种更理想的模型,因为这会使消息的传递变得更加明确。

伴随着这三大问题的是使用这种编程范式时的一系列麻烦,这些麻烦在 RPC 的 40 多年发展历史中始终阴魂不散,包括:如何从故障或错误中恢复;如何始终保证操作的正确顺序;RPC 范式强制使用者进行同步编程方式;RPC 的调用-响应模型使得因系统过载而导致消息无法正常处理时,对优先级的排列变得相当困难。

随后发布的 RFC 707 草案继承了 RFC 684 的思想,并提出了一个新问题,即各种服务,例如 TELNET 与 FTP 之间的资源共享问题。因为这些服务各自具有不同的接口,因此使用者必须了解他们的操作端口与命令。该草案的作者提出了一个建议:为远程过程的执行定义一个通用的接口,该接口接受一个参数列表,并依然遵循 RPC 的调用-响应模型。虽然这一提议并未解决 RPC 684 中所提出的问题,但这一模型在之后依然得到了许多系统的采纳。

CORBA

CORBA 是对面向对象语言的一种抽象,允许开发者进行跨机器、跨语言的通信。CORBA 通过接口定义语言(IDL)指定远程对象的接口。IDL 用于生成远程系统中的对象接口在本机中的桩代码,并且在实际的语言实现与抽象接口之间生成映射关系。

CORBA 的试图为应用开发者带来几点益处:不依赖于具体的语言、操作系统以及架构;将 IDL 中的抽象类型映射为具体实现所带来的静态类型特性;以及对象在不同机器之间的传输。CORBA 承诺,通过使用映射,远程方法调用的使用就与本地调用一样简单,甚至与分布式系统相关的异步也可被映射为本地异常进行处理。

但是,Vinoski 在 2003 年表示,仅基于透明性这一点对于编程语言与抽象进行评估的方式是有缺陷的。在他看来,IDL 映射的目的在于将中间件抽象直接合并至编程语言的领域中,通过这种透明性减少编程语言与中间件这两者之间的阻抗失调。但问题在于,不恰当的透明性可能会掩盖分布式计算中出现的某些问题,例如并发与部分失败相关的问题。

对RPC 范式的批评

Tanenbaum 与 van Renesse 对 RPC 范式提出了尖锐的批评,他们认为将远程调用与本地调用一视同仁的思想在本质上就是错的,RPC 试图打造的透明性也是根本不可能实现的。他们认为为远程访问专门设计一种协议是更好的做法。

Tanenbaum 与 van Renesse 的批评意见涵盖了 RFC 684 草案中已经提到的几点内容:延迟、缺乏并行性、异常处理以及故障检测等等。此外,他们还提出了一些批评意见:

单线程服务器

如果服务器无法立即向客户端发送响应,比如它正在等待来自另一台服务器的输入。在这种情况下,不仅服务器端产生了阻塞,客户端也无法继续执行本地计算过程。

两军问题

怎样才能让两台服务器对于某个 RPC 的成功执行以及收到响应的结果达成一致呢?虽然某一方可以向对方发送确认信息,但对方还得向这个确认信息发送另一个确认信息以再次确认。因此无论发送几次确认都无法实现 100% 的一致性。这一主题其实也是一致性问题的核心,许多与分布式系统相关的文献对其进行了更深入的探讨。

参数

Tanenbaum 与 van Renesse 也叙述了参数传递与参数封送的问题,这一问题在 CORBA 等有可能包含引用的对象系统中显得更为严重。在这种情况下,为了保证引用的有效性,必须使用某种特定的分布式引用。

幂等性

最后一个问题是如何跨网络表达只执行一次的语义,作者在此处强调了幂等性(idempotence)的重要性。简单来说,具有幂等性的操作即使经过多次执行,其结果与只执行一次也没有区别。举例来说,HTTP 中的 PUT 就具有幂等性的语义,而 POST 则不具有这一语义。作者提到了一个可能发生的场景:假设服务器在完成某个操作之后突然崩溃而来不及发送确认信息,客户端就有可能在超时之后再次发送这个实际上已经完成的请求,如果此时服务器完成了重启,就有可能再次执行这一操作。而如果该操作不满足幂等性,就可能产生一些意外的副作用。

分布式计算备忘录

Jim Waldo 和 Sam Kendall 等人共同撰写了一篇非常有名的论文“分布式计算备忘录”,这篇论文在 Reddit 上被人推荐为“每个程序员都应当至少读上两篇”的论文。在这篇论文中,作者表示“忽略本地计算与分布式计算之间的区别是一种危险的思想”,特别指出了 Emerald、Argus、DCOM 以及 CORBA 的设计问题。作者将这些设计问题归纳为“三个错误的原则”:

  1. “对于某个应用来说,无论它的部署环境如何,总有一种单一的、自然的面向对象设计可以符合其需求。”
  2. “故障与性能问题与某个应用的组件实现直接相关,在最初的设计中无需考虑这些问题。”
  3. “对象的接口与使用对象的上下文无关”

十年一轮回的错误

Waldo 表示,每过 10 年,人们就会再次尝试将本地计算与远程计算的设计揉合在一起,再一次犯下相同的错误。他再次强调:本地计算与远程计算的本质是完全不同的。

延迟

最明显的区别就在于延迟问题:如果忽略了延迟问题,软件的性能就会受到直接影响。Waldo 表示,“依赖于底层硬件速度的逐步提高”是错误的,一些实际的问题是很难通过测试找出的。性能分析是一个复杂的问题,在某一时刻表现良好的设计未必永远是合适的。

内存访问

Waldo 对内存访问的批评是特定于 CORBA 与它的继任者的:对象可能会引用在同一地址空间内的指针,但一旦对象产生了移动,这些指针就会变得无效化。他认为处理这一问题的一种途径是使用分布式共享内存,但在实践上更常见的做法是使用封送或 CORBA 引用替换技术。

局部故障

作者在最后谈到了一个最本质的问题:局部故障。在本地计算中,故障都是可检测的。而在分布式计算中,相互独立的组件可能会产生故障,并且故障可能是局部的。

舒适感胜于正确性

在文章的开头部分曾经提到了 Vinoski 对于 RPC 的批评,他认为选择 RPC 的唯一原因在于开发者的舒适感。在提出这一说法几年之后,他提出了几个非常重要的论点:

  • IDL 的阻抗失调:对基础类型进行映射可能比较简单,但复杂的类型是非常难以映射的。
  • 可伸缩性:RPC 范式本身并没有对缓冲提供任何支持,或是提出任何缓解高延迟的机制,它仍然以一种偏命令式的操作构建分布式应用。
  • REST:REST 本身是一种很好的思想,它为管理分布式资源的问题提出了特别的应对方式。但大多数基于 REST 打造的框架都改变了这一抽象思想,仍然重复了这一问题。

分布式编程语言

当我们在谈到分布式编程语言时,多数开发者所想到的其实只是如何用一般性的编程语言去构建分布式系统。实际上,只要某种语言支持并发元素,并且能够打开一个网络套接字,那么就能够构建一个分布式系统。而真正的分布式编程语言为分布式特性提供了第一等的支持。像 Go 这样的语言更像是一种并发语言,它为并发提供了第一等的支持。虽然并发是分布式中的一个重要部分,但他们毕竟还是不同的主题。

Erlang 则为分布式提供了第一等的支持,它虽然同样使用了 RPC 机制,但更倾向于在进程之间使用异步消息传递方式。受到这一设计优秀表达能力的激励, Distributed Process Akka 等框架也随之出现,以提供 Erlang 风格的语义能力。


感谢杜小芳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-04-28 19:0013802
用户头像

发布了 428 篇内容, 共 172.0 次阅读, 收获喜欢 38 次。

关注

评论

发布
暂无评论
发现更多内容

浅谈测试用例设计 | 京东云技术团队

京东科技开发者

测试 测试用例 测试用例设计 企业号 4 月 PK 榜

电力行业信息化年会 华为解读“低碳、安全、发展”新思路

YG科技

如何在微服务下保证事务的一致性 | 京东云技术团队

京东科技开发者

架构 微服务 事务 一致性 企业号 4 月 PK 榜

硬核!阿里P8耗时6月打造的架构师速成手册,颠覆你对架构师的认知

Java你猿哥

架构 分布式 ssm 软件架构 架构师

企业如何两步实现数据资产化?

星环科技

数据资产化

聊聊「低代码」的实践之路

Java 架构 低代码

分布式存储技术(下):宽表存储与全文搜索引擎的架构原理、特性、优缺点解析

星环科技

分布式 全文搜索

用友iuap 让企业数智化能力深入、让业务价值浅出

用友BIP

用友 用友iuap 用友技术大会 数智底座

MySQL8.0.32的安装与配置

Java你猿哥

Java MySQL ssm Java工程师

如何创造数据资产价值?如何对内赋能业务运营,对外创造市场价值?

星环科技

数据资产 数据要素流通

15个值得收藏的数据可视化开源工具

2D3D前端可视化开发

数据可视化 数据可视化工具 前端数据可视化 数据可视化设计 数据可视化软件

【专栏 03】数据仓库、数据集市、数据湖,你的企业更适合哪种数据管理架构?

星环科技

数据架构

大语言模型的本质:会思考的狗、聪明的马和随机鹦鹉

FN0

AIGC 大语言模型

企业数据平台建设的基石:构建统一的数据存算能力

星环科技

存算能力

电信及互联网行业数据安全内控审计建设实践 | 盾见

极盾科技

数据安全

基于公共信箱的全量消息实现

百度Geek说

大数据 即时通讯 企业号 4 月 PK 榜 公共信箱

Databend Parser 快速入门

Databend

构建系列之webpack窥探上

江湖修行

前端 Web webpack cli 构建

关于聚合根,领域事件的那点事---深入浅出理解DDD | 京东云技术团队

京东科技开发者

DDD 企业号 4 月 PK 榜 聚合根 领域事件

字节二面:HashMap线程不安全体现在哪里?

Java你猿哥

Java 线程 ssm 架构师 HashMap底层原理

请查收!一份2023年程序员不得不看的自救提升指南(彩色终极版)

Java你猿哥

Java 面试 JVM 面经

分布式技术剖析

星环科技

分布式

这一秒,困扰了程序员 50 年!

Java你猿哥

Java 程序员 ssm 计算机

Rust-Shyper:基于 Rust 语言的高可靠、开源嵌入式 Hypervisor

openEuler

Linux rust 操作系统 虚拟机 嵌入式

从入门到精通,超详细的程序员Java学习路线指南

Java你猿哥

Java 数据库 Web ssm 死磕 Java 基础

华为ISDP数字化现场作业,如何助力电力行业安监风险管控?

YG科技

统一、飞鹤等快消龙头企业,如何抓住未来10年数智化的机遇?

用友BIP

用友iuap 用友技术大会 快消行业

校企共建|阿里云与西安电子科技大学人才培养交流会顺利举行

云布道师

校企合作

分布式存储技术(上):HDFS 与 Ceph的架构原理、特性、优缺点解析

星环科技

hdfs 分布式存储 Ceph

戴尔科技园动力计划,携手中南高科赋能中小企业数字化转型

科技热闻

竞争焦点转向数智底座 用友能否再引领

用友BIP

用友iuap 用友技术大会 升级企业数智化底座

分布式计算编程模型之RPC_语言 & 开发_邵思华_InfoQ精选文章