REST技术怎么样?有什么不足之处?如何解决?
【引言】
代表性状态转移(REST)是一种软件架构风格,它定义了一套用于创建Web服务的规则。符合REST架构风格的Web服务被称为RESTful Web服务,它提供了互联网上计算机系统之间的互操作性。RESTful Web服务允许请求系统通过使用一组统一的、预定义的无状态操作来访问和操作Web资源的文本格式数据。
在互联网上,"网络资源 "最初被定义为通过URL来标识的文档或文件。然而,今天,它们有了一个更为通用和抽象的定义,它包含了在Web上可以被识别、命名、寻址、处理或执行的所有事物、实体或操作。在 RESTful Web 服务中,对资源的 URI 提出的请求,会得到一个以 HTML、XML、JSON 或其他格式的有效格式化的数据响应。这些响应可以确认对资源状态进行了一些改变,而且这些响应也可以提供指向其他相关资源的超文本链接。
当使用HTTP时,最常见的操作(HTTP方法)有GET、HEAD、POST、POST、PUT、PATCH、DELETE、CONNECT、OPTIONS和TRACE。
【历史】
Roy Fielding在2000年在加州大学欧文分校的博士论文 "Architecture Styles and the Design of Network-based Software Architectures "中对REST进行了定义,他的定义是基于HTTP 1.0的现有设计基础上,与HTTP 1.1的发展时间平行,发展了REST的架构风格。
在回顾REST的发展历程时,Fielding说:“
在这个HTTP标准化过程中,我需要为这个Web设计选择进行辩护。而在这个过程中,这个话题正迅速成为整个行业的中心,同时需要分析考虑每个人的建议,这是很难做到的。
我收到了来自500多名开发人员的意见,其中许多人都是有着几十年经验的杰出工程师,我必须从最抽象的Web交互概念到HTTP语法的最细微的细节进行解释。
在这个过程中, 我把这个模型打磨成了一套标准的规则、属性和约束,而这些规则、属性和约束现在被称为REST。”
【架构特点】
REST架构具有以下属性:
l 组件交互性能,该性能成为影响用户感知性能和网络效率的主导因素;
l 可扩展性,允许支持大量的组件和组件之间的交互。Roy Fielding将REST对可扩展性的影响描述如下:
REST的客户端与服务器的分离简化了组件的实现,降低了连接器语义的复杂性,提高了性能调优的有效性,增加了纯服务器组件的可扩展性。
分层系统允许在通信的不同点引入中间件如代理、网关和防火墙等,而又不改变组件之间的接口,从而允许它们协助通信转换或通过大规模共享缓存提高性能。
REST通过消息规则的自描述性来实现:请求之间的交互是无状态的,标准的方法和媒体类型用来表示语义和交换信息,而响应本身是可缓存的。
l 统一接口的简单化。
l 组件的可修改性,以满足不断变化的需求(即使是在应用程序运行时)。
l 通过服务代理实现组件之间的通信可视性。
l 组件的可移植性,通过将程序代码与数据一起移动,实现组件的可移植性。
l 在组件、连接器或数据内部出现故障时,在系统级别提供抗故障的可靠性。
【架构方面的规则】
一个RESTful系统定义了六个指导性规则。 这些规则限制了服务器处理和响应客户端请求的方式,这样,通过在这些规则中运行,系统就可以获得理想的非功能属性,如性能、可扩展性、简单性、可修改性、可视性、可移植性和可靠性等。如果一个系统违反了任何一个要求的规则,就不能被认为是RESTful系统。
正式的REST规则如下:
客户端-服务器架构
客户端-服务器原则前后端的分离。将用户界面的部分与数据计算存储分开,这样可以提高用户界面在多个平台上的可移植性,换句话说,多个界面可以共享一个后端服务。由于简化服务器组件,也就提高了后端服务的可扩展性。对Web应用来说,最重要的意义在于,前后端分离后的组件可以各自独立的发展,从而支持互联网多个领域的需求。
无状态
客户端与服务器之间的通信是无状态的,也就是说客户端的上下文状态不会存放在服务器上。
任何客户端的每个请求都包含了服务请求所需的所有信息,并且会话的状态如验证Token可在客户端进行保存。这个会话状态可以被服务器转移到另一个服务,如数据库等,以保持一段时间(几分钟到几天不等)的持久状态,并允许认证。
当客户端准备好过渡到一个新的状态时,需要发送请求到服务器进行更新。当一个或多个请求未完成时,客户端被认为是处于过渡状态。每一个应用状态会包含链接部分,当客户端选择启动新的状态时,可在下一次发起请求时使用。
可缓存性
与互联网世界里的网页访问一样一样,客户端和中间件可以缓存响应回来的数据。这些响应必须以隐式或显式的方式将自己定义为可缓存或不可缓存,以防止客户端在响应进一步的请求时提供陈旧或不适当的数据。
管理良好的缓存可以部分或完全消除一些客户端与服务器之间的交互,进一步提高了可扩展性和性能。
分层系统
客户端通常无法判断它是直接连接到终端服务器,还是中间件。如果在客户端和服务器之间放置一个代理或负载均衡器,这不会影响它们之间的通信,同时也不需要更新客户端或服务器的代码。
中间件服务器可以通过启用负载均衡和提供共享缓存来提高系统的可扩展性。
同时,可以将安全作为一个层添加到Web服务之上,然后将业务逻辑与安全逻辑明确分开,将安全作为一个独立的安全层,可以强制执行安全策略。
最后,这也意味着一个服务器可以调用其他多个服务器来生成响应给客户端。
按需编码(可选)
服务器可以通过传输可执行代码来临时扩展或定制客户端的功能:例如,编译后的组件,如Java小程序,或客户端JavaScript脚本。
统一接口
统一接口规则是任何RESTful系统设计的根本,它简化了整个系统的体系结构,使每个部分都能独立演进。 这种统一接口规则的四个属性是:
请求中的资源识别
在请求中可以识别单个资源,例如在RESTful Web服务中使用URIs来标识当前的请求资源。资源本身在概念上与返回给客户端的数据表示方式在概念上是分开的。例如,服务器可以将其数据库中的数据以 HTML、XML 或 JSON 的形式发送,而这些都不需要服务器端的内部逻辑实现。
对返回的资源数据可独立操作
当客户端获得一个资源数据时,包括附加的任何元数据,它有足够的信息来修改或删除这个资源数据。
自述性信息
每个消息都包含足够的信息来描述如何处理消息。例如,可以通过媒体类型指定要调用哪个解析器来解析数据。
Hypermedia作为应用状态的引擎(HATEOAS)
在访问了REST应用程序的初始URI后,REST客户端应该能够使用服务器提供的链接动态地找到它所需要的所有可用资源。随着访问请求的执行,服务器会以文本数据的方式响应,其中有可能包括指向当前可用的其他资源的超链接。客户端不需要对应用程序的结构或动态信息进行硬编码。
在网络服务中的应用
遵循REST架构约束的Web服务API称为RESTful API,这种API的定义有以下几个方面:
l 一个基本URI,如http://api.example.com/collection/。
l 标准的HTTP方法(如GET、POST、PUT、PATCH和DELETE等)。
l 数据元素状态转换的媒体类型(例如,Atom、microformats、application/vnd.collection+json等)。当前的媒体类型告诉客户端应该用何种媒体类型来处理收到的请求。可以简单如URI,也可以像Java applet那样复杂。
URI和HTTP方法之间的关系
下表显示了HTTP方法在HTTP API中的用途,当然也包括RESTful方法:
HTTP方法 |
对数据进行计算的资源,如https://api.example.com/collection或https://api.example.com/collection/item3。 |
|
POST |
调用该资源提供的操作。如果请求的结果是创建一个新的资源,其URI将在响应头中返回。 |
|
GET |
接收响应体中的数据。 |
接收响应体中的异步操作的状态。 |
PUT |
将数据存储在请求体中,也就是资源的目标状态。随后对该资源的对应的GET访问将返回更新后的数据。当然,如果有进一步的修改,如通过PATCHed、PUT等操作或者数据被DELETEd(删除后),资源的对应的GET访问也要做出相应的变化。 |
|
PATCH |
使用请求正文中的指示更新资源的某些部分状态。 |
|
DELETE |
删除该资源的状态。该资源的GET访问会返回HTTP状态404,直到新的状态被添加,如通过PUT等操作。 |
取消异步操作。 |
GET方法是安全的,因为它是只读的,对资源的访问不会导致资源的状态变化。GET、PUT和DELETE方法多次调用的结果与调用一次对资源的影响是一样的,当然响应结果可能不同,比如已经完成删除操作项目X,无法再次删除项目X。
讨论
与基于SOAP的Web服务不同,RESTful Web API没有一个 "官方 "标准。这是因为REST是一种架构风格,而SOAP是一种协议。REST本身不是一个标准,但RESTful实现利用了一些标准,如HTTP、URI、JSON和XML等标准。许多开发者也将他们的API描述为RESTful,尽管这些API实际上并没有满足上述所有的架构规则(尤其是统一接口规则)。
下表显示了传统的HTTP方法在RPC API中通常是如何使用的:
HTTP方法 |
||
GET |
返回资源集合。 |
返回单一资源。 |
POST |
创建资源集合,并返回创建的集合资源的URI, 或者创建一个资源并返回该资源的URI。 |
创建指定资源,并返回创建的成员资源的URI。 |
PUT |
更新集合资源,如果不存在,则创建资源集合。 |
更新资源,如不存在就创建。 |
PATCH |
更新集合资源,如果不存在,则创建资源集合。 |
更新资源,如不存在就创建。 |
DELETE |
删除资源集合。 |
删除资源。 |
【小结】
本文对REST架构的历史,特点,规则和在网络服务中的应用进行了介绍。
【不足之处】
其中有一条值得探讨,就是统一接口的规则。
这个规则的好处是对资源操作指定统一的接口,使得开发工作非常的简洁,逻辑上也能够降低复杂度。
它的缺点是增加了客户端调用和计算的复杂度,执行效率比较低。比如说在真正的业务逻辑中,我们需要一个数据模型,这个数据模型涉及到多个资源,他们分处在不同的表格当中,按照统一接口原则,我们需要对每个资源创建接口,然后分别调用,最后在客户端对数据进行计算整合。
所以在实际的项目开发中,要从全栈开发的角度出发,统筹规划。我们无需严格的按照REST的这条规则来做。
还是那句话,规则是为了把工作做得更好:复杂度低,执行效率高。规则是为产品服务的,不是相反。当规则的存在出现违背我们工作初衷的情况时,应该摒弃规则,而不是妥协于规则。
【解决方案】
针对上面的不足,一个解决方案是对于接口的设计应该按照业务逻辑来定义,接口数据定义一个数据模型,用于包含所有此业务逻辑需要的所有资源数据,对于接口来讲,这个模型的数据应该一个不多一个不少。
这样设计以后,客户端只需一次调用即可完成本次业务需求,而无需多次调用API再计算。
正如文中所说,REST没有一个“官方” 的标准,在我们的具体开发实施中,应根据自身需求,以REST架构风格规则为参考,目标是创建出简单,轻量而又快速的后端API服务。
欢迎讨论。
- 点赞
- 收藏
- 关注作者
评论(0)