为什么在Web应用程序中通常使用REST代替类似RPC的机制?


18

我最近刚开始在一家公司中使用了一个非常不寻常的自定义框架用于其Web应用程序,至少与我所知道的典型Web应用程序框架相比。代替RESTful Web服务,使用RPC机制与服务器进行通信。

与服务器通信看起来像一个简单的函数调用,但是该函数在服务器而不是客户端上执行。在服务器端,有一种方法可以定义客户端可以调用的功能。完全抽象了如何将其转换为http请求的细节。

我现在只用了很短的时间,但是似乎很方便。但是我想知道我缺少这种方法的缺点。其他人似乎都在做不同的事情,这通常对我来说是一个迹象,表明我可能做的是愚蠢或出色的事情,而前者的几率更高。


5
(但是我不是100%肯定的,所以我将其留为评论,并让真正了解自己的东西的人发布一个正确的答案)REST比RPC使用更多,因为REST接口通常更易于实现,并且较少依赖特定的基础框架/技术。
FrustratedWithFormsDesigner

11
我的印象是,大多数REST消费者更关心拥有简单的http + json API,而不是REST本身。
CodesInChaos

4
因为整个行业都疯了。
Mike Nakis


1
有争议的观点:REST和RPC之间的差异大部分是学术性的。
whatsisname

Answers:


33

REST是为Web设计的,而Web是为REST设计的。两者恰好会合在一起。Roy Fielding于2000年发表的论文《建筑风格和基于网络的软件体系结构设计》定义并引入了REST一词,并且Web和REST之间存在着重要的相互作用:Roy Fielding从事HTTP / 1.1的研究,他是第一作者,并且他利用从中学到的知识来描述REST。

因此,Web和REST结合得如此好的简单原因是,REST的定义是从Web的工作方式中提取的,并且Web是REST的实现。

这就是REST非常适合Web服务和Web应用程序的原因:因为您只需执行已经被证明可以在“人类” Web中工作的相同操作,然后将其应用于“机器” Web。

与RPC(根据问题的具体实现)位于基本在分布式计算的谬误,这是更详细地解释在白皮书由嫩Rotem公司-Gal一盎司此

  1. 网络可靠
  2. 延迟为零
  3. 带宽无限大
  4. 网络安全
  5. 拓扑不变
  6. 只有一名管理员
  7. 运输成本为零
  8. 网络是同质的

这些都是新人开始创建分布式系统时通常做出的假设。当然,所有这些都是错误的。创建分布式系统时,您需要考虑所有这些因素。

许多RPC实现的问题在于,它们试图使远程调用看起来像本地调用。但是它们完全不同:

  • 本地通话永远不会失败;您调用的子例程可能会失败,但是调用本身永远不会失败–远程调用可能会在网络上丢失
  • 本地电话是即时的;您调用的子例程可能会运行很长时间(如果陷入无限循环,甚至可能永远运行),但是调用本身根本不需要时间(嗯,最多只有几条CPU指令,如果调用是内联,但速度非常快)–远程呼叫可能长时间停留在网络上
  • 如果子例程正常返回,则结果总是返回–远程调用时,结果可能会丢失在网络上
  • 回报是即时的–远程结果可以在网络上长时间传播
  • 如果我调用一次子例程,它将只运行一次-远程调用可能会在网络上丢失或重复,因此远程例程可能在0到任意次数之间运行
  • 我恰好返回了一个结果–远程结果可能会丢失或重复,因此您可能会得到0次或多次结果
  • 如果我两次调用一个子例程,则会得到两个结果,并且我会在第一次调用的结果之前获得第二次调用的结果–您现在可能已经猜到了:使用RPC,您可能不会获得任何结果,或者只会得到第一个结果,或者只有第二个,或者第二个在第一个之前,或者第一个可能丢失,并且您两次获得了第二个,或者反过来,依此类推……
  • 如果我先致电a然后b,我先得到的结果,a然后再得到的结果b –这只是上一点的更一般的版本,使用RPC,您可能会以任何顺序获得0次或多次的两个答案中的任何一个

不得不面对上述所有的远程调用。但是,如果您的框架使远程调用与本地调用无法区分,那么您就不能这样做,因为您不知道哪些是远程调用。框架可能会为您尝试处理所有这些问题,但是问题是:框架与您对系统的了解不多。它不知道是否有呼叫实际上并不重要,如果偶尔丢失一次。因此,该框架必须具有很高的防御性,并且在延迟和带宽方面非常昂贵。

特别是因为该框架实际上无法保护您。该CAP定理说,一个分布式系统不能保持一致,可用,分区容错的同时,更确切地说,它说一旦发生分区,系统就无法继续保持一致和可用,它必须选择一个(与流行的看法相反,定理不是说当系统运行时不能同时拥有全部三个)通常,您可以同时拥有全部三个;但是一旦有了分区,就必须选择其他两个之一。该PACELC定理通过表明即使在系统工作时,你必须权衡延迟与一致性扩展了CAP定理。

这些重要的折衷是框架几乎无法屏蔽的,因为它们是特定于领域的,并且对核心设计很重要。

将其与类似Erlang的方法进行对比,该方法确实起作用:在Erlang中,所有消息发送都被视为远程,即使它们是本地的也是如此。这意味着您总是准备好应对上述所有问题(还有更多)。但是,对于本地进程,这些确实会造成一些开销。为了解决这个问题,有大量的工具,框架,库,模式和习惯用法可以处理错误处理和监督。

您尚未描述RPC框架的具体工作方式,以及所使用的语言或库,但是我强烈怀疑它属于以前的“假装网络不存在”类型。那些根本不起作用。它是没关系的处理,以除去本地和远程调用之间的区别的一切作为一个远程调用。反之,则过多地进行抽象:网络系统的一部分,如果将​​其抽象化,则会抽象出您实际上需要了解的内容。

现在,是否必须专门使用REST,这是一个完全不同的问题。如前所述,Web是为REST设计的,而REST是为Web设计的,因此两者确实很有意义,但是如果需要,您可以使用其他体系结构样式。但是您的问题中至少有一部分是关于“为什么不使用RPC”的问题,我在上面列出了原因,更确切地说,我解释了为什么我怀疑您使用的RPC 类型可能会给您带来麻烦。


标准化不是一个问题吗(假设HTTP和RPC之间没有1:1映射)?
吉米T.

好吧,有Actor模型框架可以解决所有这些问题。
罗伯特·哈维

当然,在REST接口上创建抽象层只需要一些热心的人,它很快就与RPC接口变得难以区分。
whatsisname

1
分布式计算的另一个谬误:客户端和服务器同时更新。
杰克

@杰克:这归因于“只有一个管理员”的谬论。它在白皮书中提到:...
约尔格W¯¯米塔格

5

评论中已经有好几个主意,我将在这里重复:

  1. RPC通常是特定于技术的。
  2. 开发人员最感兴趣的是JSON,而不是REST。

JSON具有一些非常好的特性。它简单,易于阅读,易于计算机解析,并且Javascript可以立即本地识别它(这是Java对象表示法)。

如果您愿意放弃REST之类的约束,那么几乎可以使用JSON完成任何您想做的事情,包括远程过程调用。您要做的就是建立合适的协议。实际上,这样的协议已经存在:JSON-RPC。

--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}

-1

RPC和REST只是具有优缺点的不同方法,两者都取决于上下文而有价值。最好将REST描述为与资源一起使用,其中RPC更多地是关于动作的。RPC客户端以多种方式与服务实现紧密结合,并且在不破坏客户端的情况下更改服务实现变得非常困难。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.