REST 学习 1 - 推导 REST

1,479 阅读9分钟
原文链接: www.jianshu.com

本系列的内容主要是对Roy Thomas Fielding博士《架构风格与基于网络的软件架构设计》博士论文的学习摘要。

1 从“空”风格开始

无论是建筑还是软件,人们对架构设计的过程都有着两种常见的观点。第一种观点认为设计师一切从零开始——一块空的石板、白板、或画板——并使用熟悉的组件建造出一个架构,直到该架构满足希望的系统需求为止。第二种观点则认为设计师从作为一个整体的系统需求出发,此时没有任何约束,然后增量地识别出各种约束,并将它们应用于系统的元素之上,以便对设计空间加以区分,并允许影响到系统行为的力量(forces)与系统协调一致,自然地流动。第一种观点强调创造性和无限的想象力,而第二种观点则强调限制和对系统环境的理解。REST是使用后一种过程发展而成的。随着增量地应用一组约束,已应用的约束会将架构的过程视图区分开,图5-1至5 -8以图形化的方式依次描述了这个过程。
“空”风格(图5-1)仅仅是一个空的约束集合。从架构的观点来看,空风格描述了一个组件之间没有明显边界的系统。这就是我们描述REST的起点。


图5-1:“空”风格

2 客户-服务器

客户-服务器约束背后的原则是分离关注点。通过分离用户接口和数据存储这两个关注点,我们改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。然而,对于 Web来说,最重要的是这种关注点的分离允许组件独立地进化,从而支持多个组织领域的Internet规模的需求。


图5-2:客户-服务器风格

3 无状态

我们接下来再为客户-服务器交互添加一个约束:通信必须在本质上是无状态的,因此从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器上的上下文,会话状态因此要全部保存在客户端。
这个约束导致了可见性、可靠性和可伸缩性三个架构属性。
1) 改善了可见性是因为监视系统不必为了确定一个请求的全部性质而去查看该请求之外的多个请求。
2) 改善了可靠性是因为它减轻了从局部故障中恢复的任务量。
3) 改善了可伸缩性是因为不必在多个请求之间保存状态,从而允许服务器组件迅速释放资源,并进一步简化其实现,因为服务器不必跨多个请求管理资源的使用。
与大多数架构上抉择一样,无状态这一约束反映出设计上的权衡。其缺点是:由于不能将状态数据保存在服务器上的共享上下文中,因此增加了在一系列请求中发送的重复数据(每次交互的开销),可能会降低网络性能。此外,将应用状态放在客户端还降低了服务器对于一致的应用行为的控制,因为这样一来,应用就得依赖于跨多个客户端版本(译者注:例如多个浏览器窗口)的语义的正确实现。


图5-3:客户-无状态-服务器风格

4 缓存

为了改善网络的效率,我们添加了缓存约束,从而形成了客户-缓存-无状态-服务器风格(图5-4)。缓存约束要求一个请求的响应中的数据被隐式地或显式地标记为可缓存的或不可缓存的。如果响应是可缓存的,那么客户端缓存就可以为以后的相同请求重用这个响应的数据。


图5-4:客户-缓存-无状态-服务器风格

5 统一接口

使REST架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口(图5-6)。通过在组件接口上应用通用性的软件工程原则,整体的系统架构得到了简化,交互的可见性也得到了改善。实现与它们所提供的服务是解耦的,这促进了独立的可进化性。然而,付出的代价是,统一接口降低了效率,因为信息都使用标准化的形式来转移,而不能使用特定于应用的需求的形式。REST接口被设计为可以高效地转移大粒度的超媒体数据,并针对Web的常见情况做了优化,但是这也导致了该接口对于其他形式的架构交互并不是最优的。


图5-6:统一-客户-缓存-无状态-服务器风格


为了获得统一的接口,需要有多个架构约束来指导组件的行为。REST由四个接口约束来定义:资源的识别(identification of resources)、通过表述对资源执行的操作、自描述的消息(self-descriptive messages)、以及作为应用状态引擎的超媒体。这些约束将在5.2节中讨论。

6 分层系统

为了进一步改善与Internet规模的需求相关的行为,我们添加了分层的系统约束(图5-7)。
分层系统的好处
1、降低了系统设计的复杂性
分层系统风格通过限制组件的行为(即,每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。通过将组件对系统的知识限制在单一层内,为整个系统的复杂性设置了边界,并且提高了底层独立性。
2、中间件的使用
我们能够使用层来封装遗留的服务,使新的服务免受遗留客户端的影响,通过将不常用的功能转移到一个共享的中间组件中,从而简化组件的实现。中间组件还能够通过支持跨多个网络和处理器的负载均衡,来改善系统的可伸缩性。
分层系统的缺点
分层系统的主要缺点是:增加了数据处理的开销和延迟,因此降低了用户可觉察的性能。对于一个支持缓存约束的基于网络的系统来说,可以通过在中间层使用共享缓存所获得的好处来弥补这一缺点。在组织领域的边界设置共享缓存能够获得显著的性能提升。这些中间层还允许我们对跨组织边界的数据强制执行安全策略,例如防火墙所要求的那些安全策略。
分层系统约束和统一接口约束相结合,导致了与统一管道和过滤器风格类似的架构属性。尽管REST的交互是双向的,但是超媒体交互的大粒度的数据流每一个都能够被当作一个数据流网络来处理,其中包括一些有选择地应用在数据流上的过滤器组件,以便在数据传递的过程中对它的内容进行转换。在REST 中,中间组件能够主动地转换消息的内容,因为这些消息是自描述的,并且其语义对于中间组件是可见的。


图5-7:统一-分层-客户-缓存-无状态-服务器风格

7 按需代码

我们为REST添加的最后的约束来自于3.5.3小节中描述的按需代码风格(图5-8)。通过下载并执行applet形式或脚本形式的代码,REST允许对客户端的功能进行扩展。这样,通过减少必须被预先实现的功能的数目,简化了客户端的开发。允许在部署之后下载功能代码也改善了系统的可扩展性。然而,这也降低了可见性,因此它只是REST的一个可选的约束。
可选的约束的想法似乎有些矛盾。然而,在设计一个包含多个组织边界的系统的架构时,它确实是有用的。这意味着只有当已知对于整个系统的某些领域有效的情况下,架构才会从可选的约束得到好处(或蒙受损失)。例如,如果已知一个组织中的所有客户端软件都支持Java applet[45],那么该组织中的服务就能够构造为可以通过下载Java类来增强客户端的功能,以便从可选的约束得到好处。然而,与此同时,该组织的防火墙可能会阻止转移来自外部资源的Java applet,因此对于Web的其余部分来说,这些客户端似乎是不支持按需代码的。一个可选的约束允许我们设计在一般的场合下支持期待的行为的架构,但是我们需要理解,这些行为可能在某些环境中无法使用。


图5-8:REST风格

8 风格推导小结

REST由一组选择用来在候选架构上导致想要得到的属性的架构约束组成。尽管这些约束每一个都能够独立加以考虑,但是根据它们在通用的架构风格中的来源来对它们进行描述,使得我们理解选择它们背后的基本原理更加容易。图5-9根据第3章中调查过的基于网络的架构风格图形化地描述了REST约束的来源。