本文讨论的内容主要是请求风格,所以本文中所说RPC侧重于HTTP请求风格,而非java中的RPC设计模式。
有关REST和RPC的讨论或争论一直活跃在各个技术角落,最近也关注了不少,看了很多人的看法之后,我意识到这个问题可以帮助我照亮自己的知识死角:为什么我喜欢REST的请求风格(资源导向)比RPC(操作导向)多一点呢? 是因为RPC的请求风格天生邪恶吗? 还是REST就是灵丹妙药?
两种请求风格长分别长什么样子
在比较这两种请求风格之前,让我们看看他们究竟长什么样子。
HTTP 请求
RPC和REST都是使用HTTP协议(如果你对rpc有其他认识,你可以忽略这句话)。http协议就是一个request/response协议。
一个基本的HTTP请求包含如下:
每个HTTP动词又有如下特点:
上面这个表格中只是展示了RPC和REST API中常用的几个HTTP动词
RPC: 一个基于操作的请求风格
RPC首字母缩略词有很多含义,远程过程调用(Remote Procedure Call)也有很多的形式。
在这篇文章中,当我谈论RPC我们一般都指的是:你的GET或POST方法是一个什么操作。
使用这种类型的RPC,您可以通过HTTP作为传输协议来操作数据。
就我目前所知,对于这种风格基本上没什么明确的约定和规则。
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata":"another value"
}
那么人们是怎么选择GET还是POST呢?
REST: 一种基于资源(resource)的请求风格
我不会详细解释到底什么是REST,你可以阅读Roy Fielding的论文和REST cookbook的更多细节。
为了聚焦本文的主题,我们长话短说:使用REST API,你是将数据作为资源(resource),你通过HTTP协议使用正确的HTTP动词操作,注意,是正确的动词:
GET /someresources/anId
PUT /someresources/anId
{"anotherdata":"another value"}
上例子
下面是分别用RPC和REST两种方式来编写的API:
RPC和REST大决战
既然大家都在一个劲的争论到底谁好,或者REST就是好,RPC就是不好,等等。为了能把问题说清楚,我们试图寻找一些比较指标,然后对二者进行一个全方位的对比,看最后是谁胜出?
下面是我们列举的一些指标,来比较这两种风格:
颜值
看起来两种风格都可以设计出丑的API,也都可以设计出美的API。平手。
设计性
设计RPC API看起来更容易:
当你处理一个现有的系统时,因为它通常面向操作,所以基于RPC的API与之天然匹配。但RPC API的设计需要设计人员严格的实现一致性API,因为实际上它没有什么约束。完全依赖于设计人员的一致性执行能力。
如果你主要是处理数据,REST API可能更容易一些。
但某些情况下,设计一个REST API似乎比RPC更难一点,因为它给你定了一个框框,让你实现一致的API,让你必需依赖于资源,而不是操作。
这两个都需要去处理命名的一致性。
这两种风格都依赖于具体项目的具体情况,所以真的没法分辨哪个设计起来更容易一些。
所以,平手。
API 定义语言
你可以使用例如Swagger, RAML or blueprint等这些api 定义语言来很好地描述这两种风格。
平手。
可预测性和语义
使用RPC,语义大部分时候是依赖在端点上的,并且没有对其含义的全局共享理解,什么意思呢?就是没有一个规范和约定。 例如,删除一个项目:
还有比如resign操作,你可以命名成下面任何一个似乎都没什么问题:
使用RPC,您依赖于人类对端点的含义的理解来理解它的作用,因此您可以对调用此端点时发生的事情进行精细的人工可读描述。
使用REST,语义依赖主要依赖于HTTP动词。 动词的语义是全局共享的,约定好的。 删除项目的唯一方法是:
如果用户想注销,您可以这样做:
REST比RPC更可预测,因为它依赖于HTTP动词的共享语义。 你不知道具体发生了什么,但你大概知道自己要做什么。
本局 REST 胜出。
超媒体性
这两种风格都是使用的HTTP的请求,所以都可以设计出超媒体(hypermedia)的API。
平手。
可缓存性
我们经常可以在网上看到选择REST的一个致命的理由就是http 缓存。
但看了HTTP RFC后,我不同意这个论点(也许我理解的不够深刻)。 当然,如果你的RPC API所有请求都使用POST,缓存处理起来可能有点棘手。 如果你使用GET和POST的话,你的RPC API也将能够获得与REST API相同的缓存能力。
所以,这局平手!
可用性
从开发人员的角度来看,两种样式都使用HTTP协议,因此RPC和REST请求之间基本没有区别。
平手。
总比分
指标 | 胜出方 |
---|---|
颜值 | 平手 |
设计性 | 平手 |
API 定义语言 | 平手 |
可预测性和语义 | REST |
超媒体性 | 平手 |
可缓存性 | 平手 |
可用性 | 平手 |
REST真的就赢了吗?
REST胜出要归结于“可预测性和语义”这一项指标。
那么,是不是就可以此断言基于资源比基于操作好吗?
No.
RPC和REST各有利弊,各有价值(我真的不想说出如此没有性格的话)。 你甚至可以在单个API中混合使用这两种方法。虽然我并不想得出这样的结论,但根据上面的分析确实是这样。
具体环境,这是关键。 没有灵丹妙药的解决方案,也没必要盲目去追随时尚,你总是必须在一个具体环境中去思考,用我们程序猿的话就是“上下文”, Context,在选择解决方案时必须务实。
至少,我现在知道为什么我喜欢基于资源的这种模式(REST)了:其可预测性以及充分利用HTTP协议特性。
你呢?
最后说一句:在如今这个功能编程还是主流的时代,基于操作的请求风格也是有其现实意义的,但在微服务时代(或者说在微服务场景下)呢?
本文分享自 ImportSource 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!