我试图在REST和JSON-RPC之间做出选择,为web应用程序开发API。它们是如何比较的?

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


当前回答

我已经对这个问题进行了一些详细的研究,并认为纯REST的局限性太大,RPC是最好的,尽管我的大多数应用程序都是CRUD应用程序。如果您坚持使用REST,那么您最终将会挠头思考如何轻松地将另一个所需的方法添加到API中以实现某些特殊目的。在许多情况下,使用REST实现这一点的唯一方法是为它创建另一个控制器,这可能会使程序过于复杂。

如果您决定使用RPC,唯一的区别是您显式地将动词指定为URI的一部分,这是清晰的、一致的、bug较少的,而且确实没有麻烦。特别是如果你要创建一个超越简单CRUD的应用程序,RPC是唯一的选择。我对REST的纯粹主义者还有另一个问题:HTTP POST, GET, PUT, DELETE在HTTP中有明确的含义,这些含义被REST颠覆为其他含义,仅仅是因为它们在大多数时间都适用——但不是所有时间都适用。

在编程中,我很久以前就发现,试图用一件事来表示两件事,有时会让你吃不厌。我喜欢能够对几乎每个操作都使用POST,因为它提供了按方法需要发送和接收数据的自由。你不能把整个世界都放进CRUD里。

其他回答

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

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

“REST JSON-RPC”存在!是REST与“最佳实践”,最小化信息包装,简单可靠的合同。


例子

(从这个答案和教学上下文)

在处理REST时,从资源的角度考虑通常会有所帮助。在这种情况下,资源不仅仅是“银行账户”,而是该银行账户的交易……但是JSON-RPC没有指定“方法”参数,所有都是由端点的“路径”编码的。

REST Deposit with POST /Bank/Account/John/Transaction with JSON request {"jsonrpc": "2.0", "id": 12, "params": {"currency":"USD","amount":10}}. The JSON response can be something as {"jsonrpc": "2.0", "result": "sucess", "id": 12} REST Withdraw with POST /Bank/Account/John/Transaction ... similar. ... GET /Bank/Account/John/Transaction/12345@13 ... This could return a JSON record of that exact transaction (e.g. your users generally want a record of debits and credits on their account). Something as {"jsonrpc": "2.0", "result": {"debits":[...],"credits":[...]}, "id": 13}. The convention about (REST) GET request can include encode of id by "@id", so not need to send any JSON, but still using JSON-RPC in the response pack.

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

客户需要知道过程名称; 程序参数顺序,类型和计数事项。在不破坏客户端实现的情况下,在服务器端改变过程签名(参数的数量、参数的顺序、参数类型等)并不是那么容易的; RPC样式只公开过程端点+过程参数。客户不可能决定下一步该做什么。

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

It's possible (and actually mandatory) to embed links annotated with link relation types which convey meanings of these URIs; Client implementations do not need to depend on particular procedure names and arguments. Instead, clients depend on message formats. This creates possibility to use already implemented libraries for particular media formats (e.g. Atom, HTML, Collection+JSON, HAL etc...) It's possible to easily change URIs without breaking clients as far as they only depend on registered (or domain specific) link relations; It's possible to embed form-like structures in representations, giving clients the possibility to expose these descriptions as UI capabilities if the end user is human; Support for caching is additional advantage; Standardised status codes;

在REST方面还有更多的区别和优势。

如果您的服务只使用模型和GET/POST/PUT/DELETE模式就能正常工作,那么请使用纯REST。

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

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

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

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

(很抱歉括号用多了)

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

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

But my experience has been that in practice this doesn't hold up and instead you do a lot of unnecessary work to get everything right. Also the HTTP status codes often don't map to your domain logic exactly and using them in your context often feels a bit forced. But the worst thing about REST in my opinion is that you spend a lot of time to design your resources and the interactions they allow. And whenever you do some major additions to your API you hope you find a good solution to add the new functionality and you didn't design yourself into a corner already.

This often feels like a waste of time to me because most of the time I already have a perfectly fine and obvious idea about how to model an API as a set of remote procedure calls. And if I have gone through all this effort to model my problem inside the constraints of REST the next problem is how to call it from the client? Our programs are based on calling procedures so building a good RPC client library is easy, building a good REST client library not so much and in most cases you will just map back from your REST API on the server to a set of procedures in your client library.

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