275

我正在尝试在 REST 和 JSON-RPC 之间进行选择,以便为 Web 应用程序开发 API。他们如何比较?

2015 年更新:我发现 REST 更容易开发和用于在 Web/HTTP 上提供服务的 API,因为 API 可以利用客户端和服务器都理解的现有且成熟的 HTTP 协议。例如,API 可以使用响应代码、标头、查询、帖子正文、缓存和许多其他功能,而无需任何额外的工作或设置。

4

15 回答 15

242

RPC 的根本问题是耦合。RPC 客户端以多种方式与服务实现紧密耦合,并且在不破坏客户端的情况下更改服务实现变得非常困难:

  • 客户需要知道程序名称;
  • 程序参数顺序、类型和计数很重要。在不破坏客户端实现的情况下,在服务器端更改过程签名(参数数量、参数顺序、参数类型等)并不容易;
  • RPC 风格只公开过程端点 + 过程参数。客户无法确定下一步可以做什么。

另一方面,在 REST 风格中,通过在表示(HTTP 标头 + 表示)中包含控制信息来引导客户端非常容易。例如:

  • 嵌入带有链接关系类型注释的链接是可能的(实际上是强制性的),这些链接关系类型传达了这些 URI 的含义;
  • 客户端实现不需要依赖特定的过程名称和参数。相反,客户端依赖于消息格式。这为使用特定媒体格式(例如 Atom、HTML、Collection+JSON、HAL 等)的已实现库提供了可能性
  • 可以轻松更改 URI 而不会破坏客户端,因为它们仅依赖于注册的(或特定于域的)链接关系;
  • 可以在表示中嵌入类似表单的结构,如果最终用户是人类,客户可以将这些描述公开为 UI 功能;
  • 支持缓存是额外的优势;
  • 标准化状态码;

REST 方面还有很多不同和优势。

于 2013-02-27T15:58:30.210 回答
171

我已经详细探讨了这个问题,并认为纯 REST 限制太多,而 RPC 是最好的,即使我的大多数应用程序都是 CRUD 应用程序。如果您坚持使用 REST,您最终会摸不着头脑,想知道如何轻松地将另一个需要的方法添加到您的 API 中以用于某些特殊目的。在许多情况下,使用 REST 做到这一点的唯一方法是为其创建另一个控制器,这可能会使您的程序过度复杂化。

如果您决定使用 RPC,唯一的区别是您将动词显式指定为 URI 的一部分,这样清晰、一致、错误更少,而且真的没有麻烦。特别是如果您创建的应用程序超出了简单的 CRUD,那么 RPC 是唯一的方法。我对 RESTful 纯粹主义者有另一个问题:HTTP POST、GET、PUT、DELETE 在 HTTP 中具有明确的含义,这些含义已被 REST 颠覆为其他含义,仅仅是因为它们适合大多数时间——但不是所有时间。

在编程中,我很久以前就发现试图用一件事来表示两件事会在某个时候出现并咬你。我喜欢对几乎所有操作都使用 POST 的能力,因为它提供了按照您的方法需要发送和接收数据的自由。你不能把整个世界都融入 CRUD。

于 2013-12-17T20:27:30.483 回答
31

首先,HTTP-REST 是一种“具象状态转移”架构。这意味着很多有趣的事情:

  • 您的 API 将是无状态的,因此更容易设计(在复杂的自动机中很容易忘记转换),并与独立的软件部件集成。
  • 您将被引导设计为安全的读取方法,这将易于缓存和集成。
  • 您将被引导将写入方法设计为幂等方法,这将更好地处理超时。

其次,HTTP-REST 完全兼容 HTTP(参见上一部分中的“安全”和“幂等”),因此您将能够重用 HTTP 库(存在于每种现有语言中)和 HTTP 反向代理,这将为您提供使用零行代码实现高级功能(缓存、身份验证、压缩、重定向、重写、日志记录等)的能力。

最后但同样重要的是,根据 HTTP 1.1 的设计者(以及 REST 的发明者)的说法,使用 HTTP 作为 RPC 协议是一个巨大的错误:http: //www.ics.uci.edu/~fielding/pubs/dissertation/evaluation。 htm#sec_6_5_2

于 2013-03-04T10:52:55.190 回答
27

很好的答案 - 只是想澄清一些评论。JSON-RPC 快速且易于使用,但如前所述,资源和参数是紧密耦合的,它往往依赖于使用 GET/POST 的动词(api/deleteUser、api/addUser),而 REST 提供松散耦合的资源(api/用户)在 HTTP REST API 中依赖于几种 HTTP 方法(GET、POST、PUT、PATCH、DELETE)。对于没有经验的开发人员来说,REST 实现起来稍微困难一些,但这种风格现在已经变得相当普遍,并且从长远来看它提供了更多的灵活性(让你的 API 寿命更长)。

除了没有紧密耦合的资源外,REST 还允许您避免提交给单一的内容类型——这意味着如果您的客户端需要接收 XML、JSON 甚至 YAML 格式的数据——如果内置到您的系统中,您可以返回任何使用 content-type/ 接受标头的内容。

这使您可以保持 API 足够灵活,以支持新的内容类型或客户端要求。

但真正将 REST 与 JSON-RPC 区分开来的是它遵循一系列经过深思熟虑的约束——确保架构的灵活性。这些约束包括确保客户端和服务器能够相互独立发展(您可以进行更改而不会弄乱客户端的应用程序),调用是无状态的(状态通过超媒体表示),为交互提供统一的接口, API 是在分层系统上开发的,响应可由客户端缓存。还有一个用于按需提供代码的可选约束。

然而,尽管如此 - 大多数 API 不是 RESTful(根据 Fielding),因为它们不包含超媒体(响应中嵌入的超文本链接有助于导航 API)。您会发现大多数 API 都类似于 REST,因为它们遵循 REST 的大部分概念,但忽略了这个约束。然而,越来越多的 API 正在实现这一点,并且它越来越成为一种主流实践。

这也为您提供了一些灵活性,因为超媒体驱动的 API(例如 Stormpath)将客户端定向到 URI(这意味着如果发生变化,在某些情况下您可以修改 URI 而不会产生负面影响),而 RPC URI 则需要静止的。使用 RPC,您还需要广泛记录这些不同的 URI,并解释它们如何相互关联。

一般来说,如果你想构建一个可扩展的、灵活的、长期存在的 API,我会说 REST 是要走的路。出于这个原因,我会说这是 99% 的时间要走的路线。

祝你好运,迈克

于 2015-02-01T07:47:09.907 回答
21

IMO,关键是行动与资源导向。REST 是面向资源的,非常适合 CRUD 操作,并且鉴于其已知的语义为第一个用户提供了一些可预测性,但是当从方法或过程实现时,会迫使您为以资源为中心的世界提供人工翻译。另一方面,RPC 非常适合面向操作的 API,您可以在其中公开服务,而不是可进行 CRUD 的资源集。

毫无疑问,REST 更受欢迎,如果您想将 API 公开给第三方,这肯定会增加一些要点。

如果不是(例如在 SPA 中创建 AJAX 前端),我的选择是 RPC。特别是 JSON-RPC,结合 JSON Schema 作为描述语言,并根据用例通过 HTTP 或 Websockets 传输。

JSON-RPC是一个简单而优雅的规范,它定义了要在同步或异步 RPC 中使用的请求和响应 JSON 有效负载。

JSON Schema是定义基于 JSON 的格式的规范草案,旨在描述 JSON 数据。通过使用 JSON Schema 描述您的服务输入和输出消息,您可以在不影响可用性的情况下使消息结构具有任意复杂性,并且可以自动化服务集成。

传输协议(HTTP 与 websockets)的选择取决于不同的因素,最重要的是您是否需要 HTTP 功能(缓存、重新验证、安全、幂等性、内容类型、多部分......)或者您的应用程序是否需要交换高频率的消息。

到目前为止,这在很大程度上是我对这个问题的个人看法,但现在对于那些阅读这些行的 Java 开发人员来说真的很有帮助,我去年一直在研究的框架,源于你现在想知道的同一个问题:

http://rpc.brutusin.org

你可以在这里看到一个现场演示,展示了用于功能测试的内置存储库浏览器(感谢 JSON Schema)和一系列示例服务:

http://demo.rpc.brutusin.org

希望对小伙伴有帮助!

纳乔

于 2016-01-21T23:30:23.330 回答
21

根据Richardson 成熟度模型,问题不是REST 与 RPC,而是多少 REST

在这个视图中,对 REST 标准的合规性可以分为 4 个级别。

  • 0 级:根据动作和参数进行思考。正如文章所解释的,这本质上等同于 JSON-RPC(文章针对 XML-RPC 进行了解释,但两者的论点相同)。
  • 第一级:从资源的角度思考。与资源相关的所有内容都属于同一个 URL
  • 级别 2:使用 HTTP 动词
  • 3级:仇恨

根据 REST 标准的创建者,只有 3 级服务才能称为 RESTful。然而,这是一个合规性指标,而不是质量指标。如果您只想调用一个远程函数来进行计算,那么在响应中包含相关的超媒体链接可能没有意义,也没有基于所使用的 HTTP 动词的行为差异化。因此,这样的调用本质上倾向于更像 RPC。但是,较低的合规级别并不一定意味着有状态或更高的耦合。可能,您应该尽可能多地使用REST ,而不是考虑REST 与 RPC ,但不要更多。不要为了符合 RESTful 合规标准而扭曲您的应用程序。

于 2017-10-17T14:36:57.340 回答
17

如果您的服务仅适用于模型和 GET/POST/PUT/DELETE 模式,请使用纯 REST。

我同意 HTTP 最初是为无状态应用程序设计的。

但是对于现代的、更复杂的(!)实时(Web)应用程序,你会想要使用 Websockets(这通常意味着有状态),为什么不同时使用呢?基于 Websockets 的 JSON-RPC 非常轻量,因此您有以下好处:

  • 每个客户端的即时更新(定义您自己的服务器到客户端 RPC 调用以更新模型)
  • 易于增加复杂性(尝试仅使用 REST 制作 Etherpad 克隆)
  • 如果你做得对(添加 RPC 仅作为实时的额外功能),大多数仍然可以仅使用 REST(除非主要功能是聊天或其他功能)

由于您只是在设计服务器端 API,请从定义 REST 模型开始,然后根据需要添加 JSON-RPC 支持,将 RPC 调用的数量保持在最低限度。

(抱歉括号过度使用)

于 2015-01-29T12:08:09.797 回答
17

我过去一直是 REST 的忠实粉丝,它在纸面上比 RPC 有很多优势。您可以向客户端显示不同的内容类型、缓存、重用 HTTP 状态代码,您可以通过 API 引导客户端,并且如果无论如何大部分都不是自我解释的,您可以在 API 中嵌入文档。

但我的经验是,在实践中这并不能成立,相反,你需要做很多不必要的工作才能让一切都做好。此外,HTTP 状态代码通常不会准确地映射到您的域逻辑,并且在您的上下文中使用它们通常感觉有点强迫。但在我看来,REST 最糟糕的事情是您花费大量时间来设计您的资源以及它们允许的交互。每当您对 API 进行一些重大添加时,您都希望找到一个好的解决方案来添加新功能,并且您没有将自己设计到一个角落。

这对我来说常常是浪费时间,因为大多数时候我已经对如何将 API 建模为一组远程过程调用有一个非常好的和明显的想法。如果我已经通过所有这些努力在 REST 的约束中对我的问题进行建模,那么下一个问题是如何从客户端调用它?我们的程序基于调用过程,因此构建一个好的 RPC 客户端库很容易,构建一个好的 REST 客户端库并不多,在大多数情况下,您只需从服务器上的 REST API 映射回客户端中的一组过程图书馆。

正因为如此,今天的 RPC 对我来说更简单、更自然。但我真正怀念的是一个一致的框架,它使编写自描述和可互操作的 RPC 服务变得容易。因此,我创建了自己的项目来尝试使 RPC 对自己更容易的新方法,也许其他人也觉得它很有用:https ://github.com/aheck/reflectrpc

于 2016-06-14T22:25:06.607 回答
14

为什么选择 JSON RPC:

对于 REST API,我们必须为我们可能需要的每个功能/方法定义一个控制器。因此,如果我们希望客户端可以访问 10 个方法,我们必须编写 10 个控制器来将客户端的请求与特定方法接口。

另一个因素是,即使我们为每种方法/功能使用不同的控制器,客户端也必须记住使用 POST 还是 GET。这使事情进一步复杂化。最重要的是要发送数据,如果使用 POST,则必须设置请求的内容类型。

在 JSON RPC 的情况下,事情会大大简化,因为大多数 JSONRPC 服务器都在 POST HTTP 方法上运行,并且内容类型始终是 application/json。这减轻了记住在客户端使用正确的 HTTP 方法和内容设置的负担。

不必为服务器想要向客户端公开的不同方法/功能创建单独的控制器。

为什么选择 REST:

对于服务器想要向客户端公开的不同功能,您有单独的 URL。因此,您可以嵌入这些 url。

这些观点中的大多数都是值得商榷的,完全取决于一个人的需要。

于 2017-06-12T12:39:36.313 回答
5

我认为,一如既往,这取决于...

REST 具有广泛的公众支持的巨大优势,这意味着大量的工具和书籍。如果您需要创建一个可供来自不同组织的大量消费者使用的 API,那么只有一个原因:它很受欢迎。作为一个协议,它当然是完全失败的,因为有太多完全不同的方式将命令映射到 URL/动词/响应。

因此,当您编写需要与后端对话的单页 Web 应用程序时,我认为 REST 太复杂了。在这种情况下,您不必担心长期兼容性,因为应用程序和 API 可以一起发展。

我曾经为单页 Web 应用程序使用 REST,但 Web 应用程序和服务器之间的细粒度命令很快让我发疯。我应该将其编码为路径参数吗?在身体里?查询参数?一个标题?在 URL/Verb/Response 设计之后,我不得不用 Javascript 编写这个混乱的代码,用 Java 编写解码器,然后调用实际的方法。尽管有很多工具可以做到这一点,但在您的域代码中不获取任何 HTTP 语义确实很棘手,这确实是一种不好的做法。(凝聚)

尝试为中等复杂的站点制作 Swagger/OpenAPI 文件,并将其与描述该文件中远程过程的单个 Java 接口进行比较。复杂性的增加是惊人的。

因此,对于单页 webapp,我从 REST 切换到 JSON-RPC。我开发了一个小型库,在服务器上对 Java 接口进行编码并将其发送到浏览器。在浏览器中,这为应用程序代码创建了一个代理,该代理为每个函数返回了一个 Promise。

同样,REST 之所以有它的位置,只是因为它很有名,因此得到了很好的支持。认识底层的无状态资源哲学和分层模型也很重要。但是,这些原则可以很容易地用于 RPC 模型。JSON RPC 在 HTTP 上工作,因此它在这方面具有与 REST 相同的优势。不同之处在于,当您不可避免地遇到无法很好地映射到这些原则的这些功能时,您不会被迫做很多不必要的工作。

于 2017-10-13T07:26:57.050 回答
2

最好在 REST 和 JSON-RPC 之间选择 JSON-RPC 来开发更易于理解的 Web 应用程序 API。JSON-RPC 是首选,因为它与方法调用和通信的映射很容易理解。

选择最合适的方法取决于约束或主要目标。例如,就性能是一个主要特征而言,建议使用 JSON-RPC(例如,高性能计算)。但是,如果主要目标是不可知论,以便提供通用接口以供其他人推断,则建议使用 REST。如果您需要同时实现这两个目标,建议同时包含这两个协议。

实际上将 REST 从 JSON-RPC 中分离出来的事实是,它遵循了一系列经过深思熟虑的约束——确认了架构的灵活性。约束包括确保客户端和服务器能够相互独立增长(可以进行更改而不会弄乱客户端的应用程序),调用是无状态的(状态被视为超媒体),统一的接口是为交互提供的,API 在分层系统上是先进的(Hall,2010)。JSON-RPC 快速且易于使用,但是如前所述,资源和参数是紧密耦合的,它可能依赖于使用 GET/POST 的动词(api/addUser、api/deleteUser),而 REST 提供松散耦合的资源(api /users) 在 HTTP 中。REST API 依赖于几种 HTTP 方法,例如 GET、PUT、POST、DELETE、PATCH。

JSON(表示为 JavaScript Object Notation)是一种轻量级的数据交换格式,易于人类阅读和编写。机器可以轻松解析和生成。JSON 是一种完全独立于语言的文本格式,但实践的约定是由 C#、C、C++、Java、Perl、JavaScript、Python 等语言家族的程序员所熟悉的。这些属性使 JSON 成为一种完美的数据交换语言和更好的选择。

于 2016-06-15T10:14:47.757 回答
1

REST 与 HTTP 紧密耦合,因此如果您只通过 HTTP 公开您的 API,那么 REST 更适合大多数(但不是全部)情况。但是,如果您需要通过消息传递或 Web 套接字等其他传输方式公开您的 API,则 REST 不适用。

于 2016-05-25T20:52:28.397 回答
1

错误的问题:强加一个不存在的摩尼教!

您可以将 JSON-RPC 与“较少动词”(无方法)一起使用,并保留 sendo id、参数、错误代码和警告消息所需的最小标准化。JSON-RPC 标准没有说“你不能是 REST”,只说如何打包基本信息。

“REST JSON-RPC”存在!是具有“最佳实践”的 REST,用于最少的信息打包,具有简单而可靠的合同。


例子

(从这个答案和教学背景)

在处理 REST 时,通常从资源方面的思考开始会有所帮助。在这种情况下,资源不仅仅是“银行账户”,而是该银行账户的交易......但 JSON-RPC 没有强制“方法”参数,所有这些都由端点的“路径”编码。

  • 带有JSON 请求的REST存款。JSON 响应可以是POST /Bank/Account/John/Transaction{"jsonrpc": "2.0", "id": 12, "params": {"currency":"USD","amount":10}}
    {"jsonrpc": "2.0", "result": "sucess", "id": 12}

  • REST Withdraw with POST /Bank/Account/John/Transaction... 类似。

  • ... GET /Bank/Account/John/Transaction/12345@13... 这可能会返回该确切交易的 JSON 记录(例如,您的用户通常希望在他们的帐户上记录借记和贷记)。像{"jsonrpc": "2.0", "result": {"debits":[...],"credits":[...]}, "id": 13}. 关于 (REST) GET 请求的约定可以包括通过“@id”对 id 进行编码,因此不需要发送任何 JSON,但仍然在响应包中使用 JSON-RPC。

于 2017-01-16T22:37:56.753 回答
0

如果您请求资源,那么 RESTful API 在设计上会更好。如果你请求一些复杂的数据,除了简单的 CRUD 之外,还有很多参数和复杂的方法,那么 RPC 是正确的选择。

于 2016-07-20T06:54:14.623 回答
-3

我将 vdata 用于 RPC 协议:http: //vdata.dekuan.org/

1、PHP和JavaScript都可以。2、跨域资源共享(CORS)调用还是可以的。

于 2016-10-30T16:22:28.127 回答