RPC vs RESTful endpoints.

huangapple go评论43阅读模式
英文:

RPC vs restful endpoints

问题

我花了比我愿意承认的更多时间来理解RPC和RESTful端点之间的区别。事实上,在深入研究后,我甚至不确定我是否完全理解RPC是什么了。我并不孤单。我看到无数次有人反复要求澄清。

到目前为止,我的理解如下:

RPC和RESTful端点在本质上只是概念性的。没有标准。

两者都是调用远程服务器上的函数的方式。

对于RESTful端点,我们将HTTP方法映射到资源上的CRUD操作。

对于RPC,我们关注的是对象上的操作。

然而,在两种情况下,我们都在处理远程方法调用。

我已经看到一些人说RESTful不应该具有状态,如果具有状态,它就不是RESTful。但是,大多数RESTful端点是否都通过会话来使用状态?我的意思是,我不会让任何人在未登录的情况下删除数据。

我还读到有人说像domain(.)com/login这样的功能不是RESTful,因为它是一个操作。这似乎有道理,但由于我在服务器上编写函数的方式与编写简单的RESTful函数一样,我们称它们为RESTful还是RPC真的很重要吗?

我真的不明白我错过了什么,迄今为止StackOverflow上的帖子似乎没有解决这种困惑。

希望有人可以利用以上内容作为理解的指南提供一些见解。提前感谢。

英文:

I've spent more time than I'd like to admit trying to understand the differences between RPC and restful endpoints. In fact, after going down this rabbit hole, I'm not even sure I fully understand what RPC is anymore. And I'm not alone. I see countless messages repeatedly asking for clarification.

Here's my understanding so far:

RPC and restful endpoints are largely conceptual in nature only. There are no standards.

Both are ways of invoking a function on a remote server.

In the case of restful endpoints, we map HTTP methods to CRUD operations on a resource.

In the case of RPC, we're concerned w/actions on an object.

However, in both cases, we're addressing remote method invocation.

I've read some folks say restful shouldn't be stateful and if it is, it's not restful. But aren't most restful endpoints using state via sessions? I mean, I'm not going to let just anyone delete data w/o being logged in.

And I've also read that functions like domain(.)com/login isn't restful b/c it's an action. This seems to make sense, but since I'm not writing my functions any differently on my server than I would a simple restful function, does it really matter what we call them -- restful vs. RPC.

I truly just don't understand what I'm missing and no posts thus far on StackOverflow appear to address this confusion.

Hoping someone can provide some insight using the above as a guide for understanding. Thanks in advance.

答案1

得分: 5

这是一个很棒的问题。REST和RPC方法之间有很大的区别,我会尝试解释一下。

RPC只是允许你调用远程计算机执行某些任务。它可以是任何任务,可以具有任何输入和输出。在设计API时,你只需要定义如何命名这个任务操作以及它将具有哪些输入和输出。

步骤1:只是RPC

例如,你可以有一个名为foo的操作,具有一个输入和两个输出,像这样(我将使用JSight API的表示法,因为它支持RPC和REST API类型):

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method foo
    Params
      {
        "input-1": 123 // 一些整数
      }
    Result
      {
        "output-1": 123, // 其他一些整数
        "output-2": "一些字符串"
      }

当设计RPC API时,你可以使用任意多个此类操作。

那么,这有什么问题呢?如果我们已经有RPC,为什么还需要REST呢?

问题如下:

  1. 当你看foo方法的定义时,你根本不知道它做了什么。
  2. 当设计RPC API时,你有绝对的自由,但自由往往会是一件坏事。因为人们以不同的方式思考。你可能认为你的API很简单和优雅,但其他人可能不这么认为。

步骤2:标准化RPC

如果你是一位经验丰富的API设计师,并且使用RPC风格,你将尝试遵循某种模式,以避免上述提到的两个问题。例如,让我们假设你的foo方法返回一个客户实体。那么你永远不会像foo这样调用它,而是会像这样调用它:getCustomer,如下所示:

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method getCustomer
    Params
      {
        "input-1": 123 // 一些整数
      }
    Result
      {
        "output-1": 123, // 其他一些整数
        "output-2": "一些字符串"
      }

现在当你只看这个描述时,你可以说,这个方法返回一个客户;参数input-1是某种过滤器,很可能是ID;而output-1output-2是某些客户属性。

看,只是使用标准的方法命名方式,我们使我们的API更容易理解。

但是,我们为什么还需要REST呢?这里有什么问题呢?

问题在于,当你有几十个这样的RPC方法时,你的API看起来很混乱。例如:

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method getCustomer
  Method updateCustomer
  Method getCustomerFriends
  Method getCustomerFather
  Method askCustomerConfirmation
  # 等等...

为什么很难理解这一堆方法呢?因为这不是我们大脑的工作方式。我们的大脑总是通过实体分组动作。你自然会想到一个实体,然后想到可以对它执行的动作。例如,你可以对一个杯子做什么?拿起藏起来打破洗涤倒扣。大脑很少首先考虑动作,然后再考虑实体。我可以拿什么?杯子、球、冰淇淋、票、妻子。这不太自然。

那么,REST是什么?

步骤3:REST

REST是关于分组实体并定义与这些实体的最标准操作。

在IT中,我们通常创建、读取、写入或删除实体。这就是为什么在HTTP中有POSTGETPUTDELETE方法,这实际上是REST风格的唯一实现。

当我们按实体分组我们的方法时,我们的API变得更清晰。看:

JSIGHT 0.3

GET  /customer/{id}
PUT  /customer/{id}
GET  /customer/{id}/friends
GET  /customer/{id}/father
POST /customer/{id}/ask-confirmation

现在它比上面的RPC样式示例更容易理解。

结论

关于RPC和REST之间的差异还有很多其他问题。REST也有它的问题,就像RPC一样。但我想向你解释的主要思想是:

REST是一种标准,它可以帮助你以对人类大脑友好的方式组织你的API,以便任何开发人员都可以快速掌握你的API结构。

RPC只是一种调用远程操作的方式。

上面的所有示例都在这里汇总了:https://editor.jsight.io/r/g6XJwjV/1

英文:

It's an amazing question. There is a huge difference between REST and RPC approaches, I'll try to explain it.

RPC just lets you call some remote computer to make some job. It can be any job, and it can have any inputs and outputs. When you design API, you just define how to name this job operation and which inputs and outputs it will have.

Step 1. Just RPC

For example, you could have operation foo with one input and two outputs like that (I will use JSight API notation because it supports both RPC and REST API types):

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method foo
    Params
      {
        "input-1": 123 // some integer
      }
    Result
      {
        "output-1": 123, // some other integer
        "output-2": "some string"
      }

When you design your RPC API you can use as many such operations as you want.

So, what's the problem with this? Why do we need REST, if we already have RPC?

The problems are the following:

  1. When you look at the method foo definition you do not have the slightest idea, what it does.
  2. When you design RPC APIs you have absolute freedom, but freedom often can be a bad thing. Because people think in different fashions. You could think, that your API is easy and elegant, but other people would not think so.

Step 2. Standardized RPC

If you are an experienced API designer and you use the RPC style, you will try to follow some pattern to avoid the two faults mentioned above. For example, let's imagine, that your foo method returns a customer entity. Then you will never call it like foo, you will call it getCustomer, like this:

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method getCustomer
    Params
      {
        "input-1": 123 // some integer
      }
    Result
      {
        "output-1": 123, // some other integer
        "output-2": "some string"
      }

Ok! Now when you just look at this description, you can say, that this method returns a customer; that parameter input-1 is some filter, most possibly, ID; and output-1 and output-2 are some customer properties.

Look, just using the standard way of naming the method, we made our API much more easy-to-understand.

Still, why do we need REST? What's the problem here?

The problem is, that when you have dozens of such RPC methods, your API looks messy. E. g.:

JSIGHT 0.3

URL /rpc-api
  Protocol json-rpc-2.0
  Method getCustomer
  Method updateCustomer
  Method getCustomerFriends
  Method getCustomerFather
  Method askCustomerConfirmation
  # etc...

Why it is not easy to understand this bunch of methods? Because it is not the way our brain works. Our brain always groups actions by entity. You naturally think about an entity, and then about actions, you can do with it. E. g. what you can do with a cup? Take, hide, break, wash, turn over. And brain rarely thinks firstly about actions and then about entities. What can I take? Cup, ball, ice cream, ticket, wife. Not very natural.

So, what is REST about?

Step 3. REST

REST is about grouping entities and defining the most standard actions with these entities.

In IT we usually create, read, write, or delete entities. That's why we have POST, GET, PUT, and DELETE methods in HTTP, which is de facto the only implementation of the REST style.

When we group our methods by entities, our API becomes much clearer. Look:

JSIGHT 0.3

GET  /customer/{id}
PUT  /customer/{id}
GET  /customer/{id}/friends
GET  /customer/{id}/father
POST /customer/{id}/ask-confirmation

It is much easier to perceive now than in the RPC-style example above.

Conclusion

There are a lot of other issues, concerning differences between RPC and REST. REST has its faults as well as RPC. But I wanted to explain to you the main idea:

REST is a standard, that helps you to organize your API in a user-friendly fashion, that is comfortable for the human brain, so any developer can quickly capture your API structure.

RPC is just a way of calling remote operations.

All the examples above are gathered here: https://editor.jsight.io/r/g6XJwjV/1

答案2

得分: 2

I truly just don't understand what I'm missing

真的,我不明白我错在哪里

Not your fault, the literature sucks.

不怪你,文献糟糕。

I think you may find Jim Webber's 2011 guidance enlightening.

我认为你可能会发现吉姆·韦伯(Jim Webber)2011年的指导很有启发。

Embrace HTTP as an application protocol. HTTP is not a transport protocol which happens to go conveniently through port 80. HTTP is an application protocol whose application domain is the transfer of documents over a network.

拥抱HTTP作为应用协议。HTTP不是一个恰好通过端口80方便传输的传输协议,而是一个应用协议,其应用领域是在网络上传输文档。

HTTP, like remote procedure calls, is a request/response protocol. The client sends a message to the server, the server sends a message back. Big deal.

HTTP,就像远程过程调用一样,是一种请求/响应协议。客户端向服务器发送消息,服务器发送消息回来。没什么大不了的。

But in the REST architectural style, we're also following the uniform interface constraint. That means (among other things) that everybody understands requests the same way, and everybody interprets responses the same way.

但在REST架构风格中,我们还遵循统一接口约束。这意味着(除其他事情外)每个人都以相同的方式理解请求,每个人都以相同的方式解释响应。

And that in turn means that general purpose components (browsers, web crawlers, proxies) can understand the request and response messages, and react intelligently to those messages, without needing to know anything at all about the specialization of a particular resource.

这反过来意味着通用组件(浏览器、网络爬虫、代理)可以理解请求和响应消息,并对这些消息做出智能反应,而无需了解特定资源的专业知识。

In the case of HTTP, we're passing messages about the domain of documents; if I want information from you, I ask for the latest copy of your document. If I want to send information to you, I send you a proposed modification to your document. Maybe you respond to my modification by creating a new document and you tell me to go look at that. And so on.

在HTTP的情况下,我们传递有关文档领域的消息;如果我想从你那里获取信息,我会请求你的文档的最新副本。如果我想向你发送信息,我会向你发送对你的文档的建议修改。也许你会通过创建一个新文档来回应我的修改,并告诉我去查看它。等等。

Useful business activity, then, becomes a side effect of manipulating these documents. Or, expressed another way, the document metaphor is the facade we present to the world.

因此,有用的业务活动成为操作这些文档的副作用。或者,换句话说,文档的隐喻是我们向世界展示的外观。

And I've also read that functions like domain(.)com/login isn't restful b/c it's an action.

See above: the literature sucks.

参见上文:文献很糟糕。

Consider this resource identifier: https://www.merriam-webster.com/dictionary/login

考虑这个资源标识符:https://www.merriam-webster.com/dictionary/login

Does it work like every other resource identifier on the web? Yes. The browser knows how to make a request to GET this resource, and when Merriam-Webster answers that the browser should instead look at https://www.merriam-webster.com/dictionary/log%20on then it fetches that resource as well.

它是否像Web上的其他资源标识符一样工作?是的。浏览器知道如何请求GET这个资源,当Merriam-Webster回应浏览器应该转而查看https://www.merriam-webster.com/dictionary/log%20on时,浏览器也获取了那个资源。

The fact that "login"/"log on" are intransitive English verbs does not matter; it's an identifier, and that's all the browser needs to know.

“login”/“log on”是不及物英语动词并不重要;它是一个标识符,这就是浏览器需要知道的。

Alternatively, consider this: URL shorteners work.

或者,考虑这个:URL缩短服务有效。

Resource identifiers are a lot like variable names in a computer program; so long as the identifier satisfies the production rules of your language, you can use anything you want. The machines don't care.

资源标识符很像计算机程序中的变量名;只要标识符满足你的语言的生成规则,你可以使用任何你想要的东西。机器不在乎。

The key idea is that resources are not actions, they are "information that can be named". https://www.merriam-webster.com/dictionary/log%20on is the name of the document that describes Merriam-Webster's definition of the verb "log on".

关键思想是资源不是行为,它们是“可以命名的信息”。https://www.merriam-webster.com/dictionary/log%20on是描述Merriam-Webster对动词“log on”的定义的文件的名称。

Since the machines don't care what names we use, we can use the extra freedom that offers us to choose names that make life easier for people we care about.

由于机器不在乎我们使用什么名称,我们可以利用这种额外的自由来选择那些对我们关心的人更加方便的名称。

I've read some folks say restful shouldn't be stateful and if it is, it's not restful. But aren't most restful endpoints using state via sessions?

Stateless communication is a REST architectural constraint.

[无状态通信][

英文:

> I truly just don't understand what I'm missing

Not your fault, the literature sucks.


I think you may find Jim Webber's 2011 guidance enlightening.

> Embrace HTTP as an application protocol. HTTP is not a transport protocol which happens to go conveniently through port 80. HTTP is an application protocol whose application domain is the transfer of documents over a network.

HTTP, like remote procedure calls, is a request/response protocol. The client sends a message to the server, the server sends a message back. Big deal.

But in the REST architectural style, we're also following the uniform interface constraint. That means (among other things) that everybody understands requests the same way, and everybody interprets responses the same way.

And that in turn means that general purpose components (browsers, web crawlers, proxies) can understand the request and response messages, and react intelligently to those messages, without needing to know anything at all about the specialization of a particular resource.

In the case of HTTP, we're passing messages about the domain of documents; if I want information from you, I ask for the latest copy of your document. If I want to send information to you, I send you a proposed modification to your document. Maybe you respond to my modification by creating a new document and you tell me to go look at that. And so on.

Useful business activity, then, becomes a side effect of manipulating these documents. Or, expressed another way, the document metaphor is the facade we present to the world.


> And I've also read that functions like domain(.)com/login isn't restful b/c it's an action.

See above: the literature sucks.

Consider this resource identifier: https://www.merriam-webster.com/dictionary/login

Does it work like every other resource identifier on the web? Yes. The browser knows how to make a request to GET this resource, and when Merriam-Webster answers that the browser should instead look at https://www.merriam-webster.com/dictionary/log%20on then it fetches that resource as well.

The fact that "login"/"log on" are intransitive English verbs does not matter; it's an identifier, and that's all the browser needs to know.

Alternatively, consider this: URL shorteners work.

Resource identifiers are a lot like variable names in a computer program; so long as the identifier satisfies the production rules of your language, you can use anything you want. The machines don't care.

The key idea is that resources are not actions, they are "information that can be named". https://www.merriam-webster.com/dictionary/log%20on is the name of the document that describes Merriam-Webster's definition of the verb "log on".

Since the machines don't care what names we use, we can use the extra freedom that offers us to choose names that make life easier for people we care about.


> I've read some folks say restful shouldn't be stateful and if it is, it's not restful. But aren't most restful endpoints using state via sessions?

Stateless communication is a REST architectural constraint.

> each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server.

Cookies are one of the corners where HTTP failed to satisfy the stateless communication constraint.

> I'm not going to let just anyone delete data w/o being logged in.

Not a problem: every HTTP request carries its own Authorization metadata; you aren't supposed to "remember" previous messages in the conversation. Instead, you verify the provided credentials every time.

huangapple
  • 本文由 发表于 2023年2月14日 01:59:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439599.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定