REST vs JSON-RPC?
我正在尝试在REST和JSON-RPC之间select开发一个Web应用程序的API。 哪一个更容易用于API客户端?
2015年更新:我发现REST更易于开发和使用在Web / HTTP上提供的API,因为客户端和服务器都能够理解现有的,成熟的HTTP协议。 例如响应代码,标题,查询,post主体,caching和许多其他function都可以被API使用,而不需要任何额外的努力或设置。
RPC的根本问题是耦合。 RPC客户端以多种方式与服务实现紧密耦合,并且很难在不中断客户端的情况下更改服务实现:
- 客户需要知道程序名称;
- 程序参数的顺序,types和数量的事项。 在服务器端更改过程签名(参数的数量,参数的顺序,参数types等等)并不是很容易,而不会破坏客户端的实现。
- RPC样式不会公开除了过程端点+过程参数之外的任何内容。 客户不可能确定接下来可以做什么。
另一方面,在REST风格中,通过在表示(HTTP头+表示)中包含控制信息来引导客户端非常容易。 例如:
- 可能(并且实际上是强制性的)embedded链接注释的链接关系types,这些链接关系types传达了这些URI的含义;
- 客户端实现不需要依赖于特定的过程名称和参数。 相反,客户端依赖于消息格式。 这创造了使用已经实现的特定媒体格式库(例如Atom,HTML,Collection + JSON,HAL等)的可能性。
- 只要依赖注册(或特定领域)的链接关系,就可以轻松更改URI而不破坏客户端;
- 在表示中embedded类似表单的结构是可能的,如果最终用户是人类的话,客户可以将这些描述作为UIfunction公开;
- 支持caching是额外的优势;
- 标准状态码
REST方面有更多的差异和优势。
我已经详细地探讨了这个问题,并决定纯粹的REST是太限制了,RPC是最好的,即使我的大多数应用程序是CRUD应用程序。 如果你坚持使用REST,你最终会困惑的想知道如何轻松地为你的API添加另一个需要的方法来达到一些特殊的目的。 在很多情况下,使用REST的唯一方法是为其创build另一个控制器,这可能使程序过度复杂化。
如果你决定使用RPC,唯一的区别就是你明确地把动词指定为URI的一部分,这是清晰的,一致的,更less的错误,真正没有麻烦。 特别是如果你创build一个超出简单CRUD的应用程序,RPC是唯一的方法。 对于RESTful纯粹主义者,我有另外一个问题:HTTP POST,GET,PUT,DELETE在HTTP中已经被REST所颠覆的意义变成了其他意义,因为它们大部分时间适用 – 但不是全部时间。
在编程方面,我早就发现试图用一件事来表示两件事情会在某个时候出现并咬你。 我喜欢有能力使用POST几乎每一个行动,因为它提供了自由发送和接收数据,你的方法需要做的。 你不能把整个世界纳入CRUD。
首先,HTTP-REST是“代表性状态转移”体系结构。 这意味着很多有趣的事情:
- 您的API将是无状态的,因此devise起来要容易得多(在一个复杂的自动机中很容易忘记转换),并与独立的软件部分集成。
- 您将被devise为安全的读取方法,这将很容易caching和整合。
- 你将被devise为幂等元素的写入方法,这将会在超时的情况下处理得更好。
其次,HTTP-REST完全符合HTTP(请参阅上一部分中的“安全”和“幂等”),因此您将能够重复使用HTTP库(现有的每种语言)和HTTP反向代理,用零行代码实现高级function(caching,authentication,压缩,redirect,重写,日志logging等)。
最后但并非最不重要,根据HTTP 1.1(REST的发明人)的devise者,使用HTTP作为RPC协议是一个巨大的错误: http : //www.ics.uci.edu/~fielding/pubs/dissertation/evaluation。 HTM#sec_6_5_2
很好的答案 – 只是想澄清一些评论。 JSON-RPC的使用非常简单快捷,但是前面提到的资源和参数是紧密耦合的,它倾向于使用GET / POST来依赖动词(api / deleteUser,api / addUser),因为REST提供了松散耦合的资源(api /用户)在HTTP REST API中依赖于几种HTTP方法(GET,POST,PUT,PATCH,DELETE)。 对于缺乏经验的开发人员来说,REST的实施起来稍微困难一点,但是现在风格已经变得相当普遍,并且在长期(为您的API提供更长的使用寿命)方面提供了更多的灵活性。
除了没有紧密耦合的资源之外,REST还允许您避免承诺使用单一内容types – 这意味着如果您的客户端需要以XML,JSON或甚至YAML格式接收数据(如果已内置到您的系统中)返回使用内容types/接受头的任何一个。
这可以让您保持足够的灵活性来支持新的内容types或客户端要求。
但是真正将REST与JSON-RPC区分开来的是,它遵循一系列经过深思熟虑的约束条件 – 确保架构的灵活性。 这些约束包括确保客户端和服务器能够相互独立进化(可以在不改变客户端应用程序的情况下进行更改),调用是无状态的(状态通过超媒体表示),为交互提供统一的接口, API是在分层系统上开发的,响应可由客户端caching。 还有一个可选的限制,用于按需提供代码。
然而,所有这一切说 – 大多数API不是RESTful(根据Fielding),因为它们不包含超媒体(在响应中embedded超文本链接以帮助导航API)。 你会发现大多数API都是REST类的,因为它们遵循了REST的大部分概念,但忽略了这个约束。 然而,越来越多的API正在实现这一点,而且越来越成为主stream实践。
这也为您提供了一些灵活性,因为超媒体驱动的API(如Stormpath)将客户端引导到URI(意思是如果某些情况发生了变化,在某些情况下,您可以修改URI而不会产生负面影响),而RPC URI则需要静态的。 使用RPC,您还需要广泛地logging这些不同的URI并解释它们如何相互工作。
一般来说,如果你想构build一个可以长期使用的可扩展的,灵活的API,那么REST就是要走的路。 出于这个原因,我会说这是99%的时间的路线。
祝你好运,迈克
如果你的服务只适用于模型和GET / POST / PUT / DELETE模式,那么使用纯粹的REST。
我同意HTTP最初是为无状态应用程序devise的。
但是对于想要使用Websockets(通常意味着有状态)的现代,更复杂的(!)实时(web)应用程序,为什么不使用这两个? JSON-RPC通过Websockets是非常轻的,所以你有以下好处:
- 即时更新每个客户端(定义您自己的服务器到客户端RPC调用以更新模型)
- 容易增加复杂性(尝试使用REST制作Etherpad克隆)
- 如果你做得对(实时添加RPC),大多数仍然只能用于REST(除非主要function是聊天或其他)
由于您只是devise服务器端API,因此从定义REST模型开始,随后根据需要添加JSON-RPC支持,从而使RPC调用数量保持最小。
(并且对括号过度使用抱歉)
国际海事组织,关键是行动与资源导向。 REST是面向资源的,适合于CRUD操作,并且考虑到其已知的语义为第一个用户提供了一些可预测性,但是当从方法或过程实现时,迫使您为以资源为中心的世界提供一个人为的转换。 另一方面,RPC完全适合面向操作的API,在这里你公开服务,而不是CRUD-capable资源集。
毫无疑问,REST更受欢迎,如果要将API公开给第三方,这肯定会增加一些观点。
如果没有(例如在SPA中创buildAJAX前端的情况下),我的select是RPC。 特别是JSON-RPC,结合JSON Schema作为描述语言,并根据用例通过HTTP或Websockets传输。
JSON-RPC是一个简单而优雅的规范,它定义了要在同步或asynchronousRPC中使用的请求和响应JSON有效内容。
JSON Schema是草案规范,定义了一个基于JSON的格式,旨在描述JSON数据。 通过使用JSON Schema描述服务input和输出消息,消息结构中可以具有任意的复杂性,而不会影响可用性,服务集成可以自动化。
传输协议(HTTP vs websockets)的select取决于不同的因素,是否需要HTTPfunction(caching,重新validation,安全性,幂等性,内容types,多部分等),还是应用程序需要交换高frecuencies的消息。
到目前为止,我个人对这个问题的看法很多,但现在对于那些阅读这些代码的Java开发人员来说真的很有帮助,这个框架是我去年一直在研究的框架,由您现在想知道的同一个问题:
您可以在这里看到一个现场演示,展示用于functiontesting的内置存储库浏览器(感谢JSON Schema)和一系列示例服务:
希望它可以帮助队友!
纳乔
过去,我一直是REST的忠实粉丝,它在RPC上有很多优势。 您可以为客户端提供不同的内容types,caching,重用HTTP状态代码,您可以通过API指导客户端,如果主要不是自我解释,则可以在API中embedded文档。
但是我的经验是,在实践中这并不成立,相反,你做了很多不必要的工作来把事情做好。 此外,HTTP状态代码通常不会完全映射到您的域逻辑,并且在您的上下文中使用它们通常会感觉有点被迫。 但在我看来,最糟糕的是REST花了很多时间来devise资源和他们所允许的交互。 而且每当你做了一些重要的API添加,你希望你find一个很好的解决scheme来添加新的function,你没有devise自己的angular落已经。
这对我来说往往是浪费时间,因为大部分时间我已经有了一个非常好的和明显的想法,即如何将APIbuild模为一组远程过程调用。 如果我已经完成了所有这些努力,在REST的限制内对我的问题进行build模,接下来的问题是如何从客户端调用它? 我们的程序基于调用过程,所以构build一个好的RPC客户端库很容易,build立一个不错的REST客户端库不是很多,在大多数情况下,您只需从服务器上的REST API映射回客户端的一组过程图书馆。
正因为如此,RPC今天对我来说感觉更简单,更自然。 我真正想念的是一个一致的框架,可以很容易地编写自描述和可互操作的RPC服务。 因此,我创build了自己的项目,尝试使自己的RPC更简单的新方法,也许别人也觉得它有用: https : //github.com/aheck/reflectrpc
为什么JSON RPC:
对于REST API,我们必须为每个可能需要的function/方法定义一个控制器。 因此,如果我们有10个方法可供客户访问,则必须编写10个控制器来将客户端的请求连接到特定的方法。
另一个因素是,即使我们对每个方法/function都有不同的控制器,客户端也必须记住使用POST或GET。 这使事情进一步复杂化。 除此之外,如果使用POST,则必须设置请求的内容types。
在JSON RPC的情况下,大大简化了事情,因为大多数JSONRPC服务器在POST HTTP方法上运行,而内容types始终是application / json。 这使得记住的负载在客户端使用正确的HTTP方法和内容设置。
人们不必为服务器想要暴露给客户端的不同方法/function创build单独的控制器。
为什么selectREST:
你有不同的服务器要公开给客户端的function的URL。 因此,您可以embedded这些url。
这些问题大部分是有争议的,完全取决于一个人的需要。
根据理查森成熟度模型 ,问题不是REST与RPC ,而是REST多less?
从这个angular度来看,符合REST标准可以分为4个级别。
- 0级:从行动和参数angular度思考。 正如文章所解释的那样, 这实质上等同于JSON-RPC (本文将其解释为用于XML-RPC,但两者同样适用)。
- 1级:从资源angular度思考。 与资源相关的所有内容都属于同一个URL
- 2级:使用HTTP动词
- 等级3:HATEOAS
根据REST标准的创build者,只有三级服务可以称为RESTful。 但是,这是一个遵从性的标准 ,而不是质量标准。 如果你只是想调用一个远程函数来进行计算,那么在响应中使用相关的超媒体链接可能是没有意义的,而不是基于所使用的HTTP动词来区分行为。 所以,这样的调用本质上倾向于更像RPC。 然而,较低的合规性水平并不一定意味着有状态,或更高的耦合度。 也许,不要考虑REST和RPC ,而应该尽可能多地使用REST,但不要再使用REST。 不要为了符合RESTful合规性标准而扭曲应用程序。
REST与HTTP紧密结合,所以如果只通过HTTP公开API,那么REST更适合于大多数情况(但不是全部)。 但是,如果您需要通过其他传输(如消息传递或Web套接字)暴露您的API,则REST不适用。
我使用RPC协议的vdata: http ://vdata.dekuan.org/
1,PHP和JavaScript都不错。 2,跨源资源共享(CORS)呼叫仍然可以。
错误的问题:强加一个不存在的manichean!
您可以使用JSON-RPC和“less verb”(无方法 ),并保留sendo id,参数, 错误代码和警告消息所需的最低标准化。 JSON-RPC标准并不是说“你不可能是REST”,只是说如何打包基本信息。
“REST JSON-RPC”存在 ! 是REST的“最佳实践”,用最less的信息包装,简单而坚实的合同。
例
(从这个答案和教学环境)
在处理REST时,通常从资源的angular度思考开始有所帮助。 在这种情况下,资源不仅仅是“银行账户”,而是一个银行账户的交易…但是JSON-RPC没有强制“方法”参数,全部都是由端点的“path”编码的。
-
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 撤销
POST /Bank/Account/John/Transaction
…类似。 -
…
GET /Bank/Account/John/Transaction/12345@13
…这可能会返回一个JSONlogging的确切交易(例如,您的用户通常需要logging在他们的帐户借记和信用)。 例如{"jsonrpc": "2.0", "result": {"debits":[...],"credits":[...]}, "id": 13}
。 关于(REST)GET请求的约定可以包含“@id”的id编码,所以不需要发送任何JSON,但仍然在响应包中使用JSON-RPC。
我认为,一如既往,这取决于…
REST具有广泛的公众支持的巨大优势,这意味着大量的工具和书籍。 如果您需要制作一个由不同组织的大量消费者使用的API,那么这只是一个原因:它很受欢迎。 作为一个协议,它当然是彻底的失败,因为有太多完全不同的方法来映射到URL /动词/响应命令。
因此,当你编写一个需要与后端对话的单页网页应用时,我认为REST太复杂了。 在这种情况下,您不必担心长期的兼容性,因为应用程序和API可以一起演变。
我曾经使用REST开发单页网页应用程序,但是网页应用程序和服务器之间的细微命令很快使我疯狂。 我应该将其编码为path参数吗? 在身体? 查询参数? 头文件? 在URL / Verb / Responsedevise之后,我不得不在Javascript中使用Java中的解码器编码这个混乱,然后调用实际的方法。 虽然有很多的工具,但是在你的域代码中不要使用任何HTTP语义是非常棘手的,这是非常糟糕的做法。 (凝聚)
尝试为中型复杂站点制作Swagger / OpenAPI文件,并将其与一个描述该文件中的远程过程的单个Java接口进行比较。 复杂性增加是惊人的。
因此,我从REST切换到单页webapp的JSON-RPC。 我开发了一个小型库,在服务器上编码一个Java接口,并将其发送到浏览器。 在浏览器中,这为应用程序代码创build了一个代理,该代理返回了每个函数的承诺。
REST也是有名的,因此得到了很好的支持。 认识潜在的无状态资源哲学和分层模型也是很重要的。 但是,这些原则可以很容易地在RPC模型中使用。 JSON RPC通过HTTP进行工作,因此它在这方面与REST具有相同的优点。 不同之处在于,当你不可避免地遇到这些不符合这些原则的function时,你不会被迫做很多不必要的工作。
我觉得有一点人忘了提。 如果你已经有一个web应用程序,那么REST是可取的,因为你需要的应用服务器无论如何,你可以使用https保护…但如果你没有一个web应用程序,(只有一个应用程序),然后RPC因为您不再需要安装应用程序服务器并将其configuration为ha is,所以这是可取的。 除此之外,我也没有看到任何真正的根本优势。
在REST和JSON-RPC之间selectJSON-RPC来开发一个易于理解的Web应用程序的API会更好。 JSON-RPC是首选,因为它可以很容易地理解对方法调用和通信的映射。
select最合适的方法取决于约束或主要目标。 例如,就性能是一个主要特性而言,build议使用JSON-RPC(例如,高性能计算)。 但是,如果主要目标是不可知的,以提供一个通用的接口,由其他人推断,build议去REST。 如果您需要实现两个目标,build议包括这两个协议。
REST从JSON-RPC实际上分裂出来的事实是,它追溯了一系列经过深思熟虑的约束 – 确认了架构的灵活性。 约束条件是确保客户端和服务器能够彼此独立地增长(可以在不与客户端应用程序混淆的情况下进行更改),调用是无状态的(状态被认为是超媒体),统一的接口提供了交互,API是在分层系统上进行的(Hall,2010)。 JSON-RPC是快速且易于使用的,但是所提及的资源和参数是紧密耦合的,并且可能依赖于使用GET / POST的动词(api / addUser,api / deleteUser),而REST提供松散耦合的资源(api /用户)在HTTP中。 REST API依赖于几个HTTP方法,如GET,PUT,POST,DELETE,PATCH。 对于缺乏经验的开发人员来说,REST稍微难一些。
JSON(表示为JavaScript Object Notation)是一种轻量级的数据交换格式,对于人类来说,读取和写入都很容易。 机器parsing和生成是无忧无虑的。 JSON是一种完全独立于语言的文本格式,但实践了熟悉C#,C,C ++,Java,Perl,JavaScript,Python等众多语言家族程序员的惯例。 这样的属性使JSON成为完美的数据交换语言,是更好的select。
如果您请求资源,则RESTful API在devise上更好。 如果您请求一些复杂的数据,并且使用大量的参数和复杂的方法,而不是简单的CRUD,那么RPC是正确的select。