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一盎司此:
- 网络可靠
- 延迟为零
- 带宽无限大
- 网络安全
- 拓扑不变
- 只有一名管理员
- 运输成本为零
- 网络是同质的
这些都是新人开始创建分布式系统时通常做出的假设。当然,所有这些都是错误的。创建分布式系统时,您需要考虑所有这些因素。
许多RPC实现的问题在于,它们试图使远程调用看起来像本地调用。但是它们完全不同:
- 本地通话永远不会失败;您调用的子例程可能会失败,但是调用本身永远不会失败–远程调用可能会在网络上丢失
- 本地电话是即时的;您调用的子例程可能会运行很长时间(如果陷入无限循环,甚至可能永远运行),但是调用本身根本不需要时间(嗯,最多只有几条CPU指令,如果调用是内联,但速度非常快)–远程呼叫可能长时间停留在网络上
- 如果子例程正常返回,则结果总是返回–远程调用时,结果可能会丢失在网络上
- 回报是即时的–远程结果可以在网络上长时间传播
- 如果我调用一次子例程,它将只运行一次-远程调用可能会在网络上丢失或重复,因此远程例程可能在0到任意次数之间运行
- 我恰好返回了一个结果–远程结果可能会丢失或重复,因此您可能会得到0次或多次结果
- 如果我两次调用一个子例程,则会得到两个结果,并且我会在第一次调用的结果之前获得第二次调用的结果–您现在可能已经猜到了:使用RPC,您可能不会获得任何结果,或者只会得到第一个结果,或者只有第二个,或者第二个在第一个之前,或者第一个可能丢失,并且您两次获得了第二个,或者反过来,依此类推……
- 如果我先致电
a
然后b
,我先得到的结果,a
然后再得到的结果b
–这只是上一点的更一般的版本,使用RPC,您可能会以任何顺序获得0次或多次的两个答案中的任何一个
你将不得不面对上述所有的远程调用。但是,如果您的框架使远程调用与本地调用无法区分,那么您就不能这样做,因为您不知道哪些是远程调用。框架可能会为您尝试处理所有这些问题,但是问题是:框架与您对系统的了解不多。它不知道是否有呼叫实际上并不重要,如果偶尔丢失一次。因此,该框架必须具有很高的防御性,并且在延迟和带宽方面非常昂贵。
特别是因为该框架实际上无法保护您。该CAP定理说,一个分布式系统不能保持一致,可用,分区容错的同时,更确切地说,它说一旦发生分区,系统就无法继续保持一致和可用,它必须选择一个(与流行的看法相反,定理不是说当系统运行时不能同时拥有全部三个)通常,您可以同时拥有全部三个;但是一旦有了分区,就必须选择其他两个之一。该PACELC定理通过表明即使在系统工作时,你必须权衡延迟与一致性扩展了CAP定理。
这些重要的折衷是框架几乎无法屏蔽的,因为它们是特定于领域的,并且对核心设计很重要。
将其与类似Erlang的方法进行对比,该方法确实起作用:在Erlang中,所有消息发送都被视为远程,即使它们是本地的也是如此。这意味着您总是准备好应对上述所有问题(还有更多)。但是,对于本地进程,这些确实会造成一些开销。为了解决这个问题,有大量的工具,框架,库,模式和习惯用法可以处理错误处理和监督。
您尚未描述RPC框架的具体工作方式,以及所使用的语言或库,但是我强烈怀疑它属于以前的“假装网络不存在”类型。那些根本不起作用。它是没关系的处理,以除去本地和远程调用之间的区别的一切作为一个远程调用。反之,则过多地进行抽象:网络是系统的一部分,如果将其抽象化,则会抽象出您实际上需要了解的内容。
现在,是否必须专门使用REST,这是一个完全不同的问题。如前所述,Web是为REST设计的,而REST是为Web设计的,因此两者确实很有意义,但是如果需要,您可以使用其他体系结构样式。但是您的问题中至少有一部分是关于“为什么不使用RPC”的问题,我在上面列出了原因,更确切地说,我解释了为什么我怀疑您使用的RPC 类型可能会给您带来麻烦。