首页 文章

REST vs JSON-RPC?

提问于
浏览
222

我正在尝试在REST和JSON-RPC之间进行选择,以便为Web应用程序开发API . 哪一个更容易用于API客户端?

2018年更新:GraphQL提供了优于传统选项的几个优势,特别是它不需要在服务器和客户端之间手动规范化,非规范化和缓存数据,也可以从UI组件聚合API调用,而无需创建允许开发人员构建UI的单例客户端状态组件独立和并行 . 更新2015:我发现REST更易于开发和使用在Web / HTTP上提供的API,因为API可以利用客户端和服务器都能理解的现有和成熟的HTTP协议 . 例如,API可以使用响应代码, Headers ,查询,帖子正文,缓存和许多其他功能,而无需任何额外的工作或设置 .

16 回答

  • 2

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

    • 客户需要知道程序名称;

    • 程序参数顺序,类型和计数事项 . 在不破坏客户端实现的情况下,在服务器端更改过程签名(参数数量,参数顺序,参数类型等)并不容易;

    • RPC样式不能让客户确定接下来可以做什么 .

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

    • 有可能(实际上是强制性的)嵌入带有链接关系类型的链接,这些链接传达了这些URI的含义;

    • 客户端实现不需要依赖于特定的过程名称和参数 . 相反,客户端依赖于消息格式 . 这样就可以将已经实现的库用于特定的媒体格式(例如Atom,HTML,Collection JSON,HAL等......)

    • 只要它们仅依赖于已注册(或特定于域的)链接关系,就可以轻松更改URI而不会破坏客户端;

    • 可以在表示中嵌入类似表单的结构,如果最终用户是人,则客户可以将这些描述公开为UI功能;

    • 支持缓存是另一个优势;

    • 标准化状态代码;

    REST方面还有许多不同之处和优点 .

  • 28

    我已经详细探讨了这个问题,并认为纯REST太过限制,而RPC是最好的,尽管我的大多数应用都是CRUD应用 . 如果你坚持使用REST,你最终会想到如何为某些特殊目的轻松地为API添加另一个所需的方法 . 在许多情况下,使用REST执行此操作的唯一方法是为其创建另一个控制器,这可能会使程序过度复杂化 .

    如果您决定使用RPC,唯一的区别是您明确指定动词作为URI的一部分,这是明确的,一致的,较少的错误,并且确实没有问题 . 特别是如果你创建一个超越简单CRUD的应用程序,RPC是唯一的方法 . 我对RESTful纯粹主义者有另一个问题:HTTP POST,GET,PUT,DELETE在HTTP中具有明确的含义,这些含义已经被REST破坏为意味着其他东西,仅仅因为它们适合大部分时间 - 但不是所有时间 .

    在编程方面,我很久以前就发现尝试用一件事来表示两件事情有时会出现并咬你 . 我希望能够为每个操作使用POST,因为它提供了自由发送和接收数据的方法 . 你无法将整个世界融入CRUD .

  • 5

    首先,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

  • 146

    很棒的答案 - 只是想澄清一些评论 . JSON-RPC快速且易于使用,但是提到的资源和参数是紧密耦合的,它倾向于使用GET / POST依赖动词(api / deleteUser,api / addUser),因为REST提供了松散耦合的资源(api / users),它们在HTTP REST API中依赖于多个HTTP方法(GET,POST,PUT,PATCH,DELETE) . 对于没有经验的开发人员来说,REST稍微难以实现,但是这种风格现在变得相当普遍,并且从长远来看它提供了更大的灵活性(使您的API具有更长的使用寿命) .

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

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

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

    然而,所有这些都说 - MOST API不是RESTful(根据Fielding),因为它们没有包含超媒体(在帮助导航API的响应中嵌入了超文本链接) . 您会发现大多数API都与REST类似,因为它们遵循REST的大多数概念,但忽略了这种约束 . 但是,越来越多的API正在实现这一点,它正在成为一种主流实践 .

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

    总的来说,如果你想构建一个可以长期使用的可扩展,灵活的API,我会说REST是要走的路 . 出于这个原因,我会说这是99%的时间路线 .

    祝你好运,迈克

  • 0

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

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

    但对于现在的,更复杂的(!)实时(Web)应用程序,您需要使用Websockets(通常意味着有状态),为什么不同时使用它们呢? Websockets上的JSON-RPC非常轻巧,因此您可以获得以下好处:

    • 每个客户端上的即时更新(定义您自己的服务器到客户端RPC调用以更新模型)

    • 易于增加复杂性(尝试仅使用REST创建Etherpad克隆)

    • 如果你做得对(仅将RPC作为实时额外添加),大多数仍可用于REST(除非主要功能是聊天或其他)

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

    (并且抱歉过度使用括号)

  • 1

    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

    希望它有助于交配!

    纳乔

  • 12

    我过去一直是REST的忠实粉丝,它在RPC上有很多优势 . 您可以向客户端提供不同的内容类型,缓存,HTTP状态代码的重用,您可以通过API指导客户端,如果主要不是自我解释,您可以在API中嵌入文档 .

    但我的经验是,在实践中,这并没有成功,而是你做了很多不必要的工作来使一切正常 . 此外,HTTP状态代码通常不会准确映射到您的域逻辑,并且在您的上下文中使用它们通常会感觉有点强迫 . 但在我看来,关于REST的最糟糕的事情是你花了很多时间来设计资源和他们允许的交互 . 每当你对你的API做一些重要的补充时,你希望你找到一个很好的解决方案来添加新功能,而你并没有将自己设计到一个角落 .

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

    因此,RPC对我来说感觉更加简单和自然 . 我真正想念的是一个一致的框架,可以很容易地编写自我描述和可互操作的RPC服务 . 因此,我创建了自己的项目来尝试新的方法,使自己更容易使用RPC,也许其他人发现它也很有用:https://github.com/aheck/reflectrpc

  • 8

    根据Richardson maturity model,问题不是REST与RPC,而是REST多少?

    在此视图中,REST标准的合规性可分为4个级别 .

    • 0级:从行动和参数的角度考虑 . 正如文章所解释的那样, this is essentially equivalent to JSON-RPC (文章解释了XML-RPC,但两者都有相同的论点) .

    • 1级:从资源角度考虑 . 与资源相关的所有内容都属于同一个URL

    • level 2:使用HTTP动词

    • 等级3:HATEOAS

    根据REST标准的创建者,只有3级服务可以称为RESTful . 但是,这是合规性的衡量标准,而不是质量标准 . 如果您只想调用执行计算的远程函数,则在响应中使用相关的超媒体链接可能没有意义,也不会基于所使用的HTTP谓词区分行为 . 因此,这样的调用本身往往更像RPC . 但是,较低的合规水平并不一定意味着有状态或更高的耦合 . 也许,不应该考虑REST与RPC,而应该使用尽可能多的REST,但不能再使用REST . 不要仅仅为了符合RESTful合规性标准而扭曲您的应用程序 .

  • 14

    Why JSON RPC:

    在REST apis的情况下,我们必须为我们可能需要的每个功能/方法定义一个控制器 . 因此,如果我们有10个方法可以让客户端访问,我们必须编写10个控制器来将客户端的请求与特定方法连接起来 .

    另一个因素是,即使我们为每个方法/功能设置了不同的控制器,客户端也必须记住使用POST或GET . 这使事情进一步复杂化 . 除此之外,如果使用POST,则必须设置请求的内容类型 .

    在JSON RPC的情况下,事情大大简化,因为大多数JSONRPC服务器在POST HTTP方法上运行,内容类型总是application / json . 这样可以减少记住在客户端使用正确的HTTP方法和内容设置的负担 .

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

    Why REST:

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

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

  • 24

    如果您请求资源,那么RESTful API在设计上会更好 . 如果您使用大量参数和复杂方法请求一些复杂的数据而不是简单的CRUD,那么RPC是正确的方法 .

  • 2

    错误的问题:强加一个不存在的manichean!

    您可以将JSON-RPC与"less verb"(无方法)一起使用并保留sendo id,参数,错误代码和警告消息所需的最小标准化 . JSON-RPC标准不说"you can't be REST",只说如何打包基本信息 .

    "REST JSON-RPC" exists ! REST是"best practices",用于最小的信息打包,具有简单而可靠的 Contract .


    示例

    (来自this answer和教学背景)

    在处理REST时,通常从资源方面考虑是有帮助的 . 在这种情况下,资源不仅仅是“银行账户”,而且是该银行账户的交易......但是JSON-RPC没有义务“方法”参数,所有都由 endpoints 的“路径”编码 .

    • REST存入 POST /Bank/Account/John/Transaction ,带有JSON请求 {"jsonrpc": "2.0", "id": 12, "params": {"currency":"USD","amount":10}} .
      JSON响应可以是 {"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 .

  • 0

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

  • 17

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

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

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

    我曾经使用REST开始使用单页Web应用程序,但Web应用程序和服务器之间的细粒度命令很快让我发疯 . 我应该将其编码为路径参数吗?在身体里?查询参数? Headers ?在URL /动词/响应设计之后,我不得不用Javascript编写这个混乱,用Java解码,然后调用实际的方法 . 虽然它有很多工具,但是在你的域代码中没有获得任何HTTP语义真的很棘手,这实际上是不好的做法 . (凝聚)

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

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

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

  • 0

    我认为有一点让人忘记提及 . 如果您已经有一个Web应用程序,那么REST是可取的,因为您无论如何都需要应用程序服务器,并且您可以使用https来保护...但如果您没有Web应用程序,(只有一个应用程序),那么RPC因为您不再需要设置应用服务器并对其进行配置,因此是理想的 . 除此之外,我也没有看到任何真正的根本优势 .

  • 1

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

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

    实际上从JSON-RPC中分离REST的事实是它落后于一系列经过深思熟虑的约束 - 确认了架构灵活性 . 约束条件是确保客户端和服务器能够独立于每个客户端和服务器进行扩展其他(可以在不搞乱客户端应用的情况下进行更改),调用是无状态的(状态被视为超媒体),为交互提供统一的接口,API在分层系统上进行(Hall,2010) . JSON-RPC快速且易于使用,但是如上所述,资源和参数紧密耦合,并且可能依赖于使用GET / POST的动词(api / addUser,api / deleteUser),而REST提供松散耦合的资源(api) / users)在HTTP中 . REST API依赖于几种HTTP方法,例如GET,PUT,POST,DELETE,PATCH . 对于没有经验的开发人员来说,REST实施起来有点困难 .

    JSON(表示为JavaScript Object Notation)是一种轻量级数据交换格式,人们可以轻松读取和写入 . 机器解析和生成是免费的 . JSON是一种完全独立于语言的文本格式,但是对语言家族的程序员很熟悉,它们由C#,C,C,Java,Perl,JavaScript,Python和许多其他程序员组成 . 这些属性使JSON成为一种完美的数据交换语言,也是更好的选择 .

  • 197

    我使用vdata进行RPC协议:http://vdata.dekuan.org/

    1,PHP和JavaScript都没关系 . 2,跨域资源共享(CORS)调用仍然没问题 .

相关问题