restful架构风格设计准则(六)版本管理

读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者!

版本管理

  在前面已经提到过,一个REST系统为资源所抽象出的URI实际上是对用户的一种承诺。但反过来说,软件开发人员也很难预知一个资源的各方面特征如何在未来发生变化,从而提供一个永远不变的URI。

  在一个REST系统逐渐发展的过程中,新的属性,新的资源将逐渐被添加到该系统中。在这些更改过程中,资源的URI,访问资源的动词,响应中的Status Code将不能发生变化。此时软件开发人员所做的工作就是在现有系统上维护REST API的后向兼容性。

  当资源发生了过多的变化,原有的URI设计已经很难兼容现有资源应有的定义时,软件开发人员就需要考虑是否应该提供一个新版本的REST API。那么我们该如何对资源的版本进行管理呢?

  首先要考虑的就是,新API的版本信息是否应当包含在资源的URI中。这在各著名论坛中仍然是一个争议较大的话题。一种观点认为在不同版本的API中,一个资源拥有不同的地址在一定程度上违反了HATEOAS:URI只是用来指定一个资源所在的位置,而不是该资源如何被抽象。如果一个资源由不同的URI标示其不同的表现形式,那么用户将无法通过一个响应中所标示的URI得到其它URI所指向的表示形式。而且在URI中添加了有关版本的信息也就标示着其可能会随着时间的推移发生变化。

  一种使用独立URI的方法是基于Accept头。在一个请求中,我们常常标明了Accept头,以标示客户端希望得到的表现形式。在该头中,用户可以添加所请求的资源的版本信息:

1 GET /api/categories/1
2 Host: www.egoods.com
3 Authorization: Basic xxxxxxxxxxxxxxxxxxx
4 Accept: application/vnd.ambergarden.egoods-v3+json

  而在接收到该请求之后,服务端将返回该资源的第三个版本:

1 HTTP/1.1 200 OK
2 Content-Type: application/vnd.ambergarden.egoods-v3+json
3 Content-Length: xxx
4
5 {
6    "uri" : "/api/categories/1",
7    "label" : "Food",
8    ……
9 }

  可以看到,该方法是非常严格地遵守REST系统所提出的约束的。但其也并不是没有缺点:添加一个自定义MIME类型(Custom MIME Type)也是一个很麻烦的流程,而且在很多现有技术中都没有很好地支持它,如HTML5中的Form。因此这种方案的缺点是对REST API用户并不那么友好。

  除此之外,另一种基于重定向的解决方案也被提出。该方案允许一个REST系统提供多个版本的API,并在URI中标明版本号:

1 /api/v2/categories
2 /api/v1/categories

  这样用户可以选择使用特定版本的REST API来实现客户端功能。由于其使用固定版本的API,因此并不存在着一个资源有多种表示,进而违反了HATEOAS约束的问题。

  在REST系统的API随时间逐渐发展出众多版本的时候,系统对API的维护也将成为一个较大的问题。此时就需要逐渐退役一些年代久远的API 版本。对这些版本的退役主要分为两步:首先将其标为过期的,但是还在一段时间内支持。在这种情况下,对这些已经过期的API的访问将得到3XX响应,如301 Moved Permanently,以通知用户该URI所标示的资源需要使用新版本的URI进行访问。而再经过一段时间后,则将过期的REST API标记为废弃的。此时用户在访问这些URI时将返回4XX响应,如410 Gone。

  接下来,该REST系统还可以提供一个通用的REST API接口,并与最新版本的API保持一致:

1 /api/categories

  这样用户还可以选择一直使用最新版本的API,只是同时也需要一直对其进行维护,以保持与最新版本API的兼容性。在REST系统的API随着时间的推移逐渐发生变化的时候,该客户端也需要逐渐更新自身的功能。

  但是该方法有一个问题:由通用URI所辨识出的各个资源需要是稳定的,不能在一定时间之后被废弃,否则会给用户带来非常大的维护性的麻烦。举例来说,假设客户端逻辑添加了一系列操作分类的功能。当REST系统决定不再采用分类作为商品归类的标准,那么客户端逻辑中与分类相关的各个功能都需要进行大幅度地修改。过于频繁的这种改动很容易导致用户对该系统所提供的API失去维护的信心。因此在抽象资源时一定要努力地将各个资源的边界辨识清楚。虽然说这听起来很吓人,但是在经过仔细考虑后这种情况还是较为容易避免的。

  但是反过来说,理论常常与实际有些脱钩,更何况REST是在2000年左右提出的,无法做到能够预见到十余年后所使用的各项技术。因此在尽量符合REST所提出的各约束上提供一个最直观的,具有最高易用性的API才是王道。无限制地提供后向兼容性是一个非常困难,成本非常高的事情。因此在版本管理这一方面上来说,我们也需要尽量兼顾项目需求和完全遵从理论这两者之间的平衡。

  而在同一个版本之中,我们则需要保证API的后向兼容性。也就是说,在添加新的资源以及为资源添加新的属性的时候,原有的对资源进行操作的API也应该是工作的。

  对于一个基于HTTP的REST服务而言,软件开发人员需要遵守如下的守则以保持API的后向兼容性:

  1. 不能在请求中添加新的必须的参数。
  2. 不能更改操作资源的动词。
  3. 不能更改响应的HTTP status。

  而前向兼容性则显得没有那么重要了。REST服务的前向兼容性要求现有的服务兼容未来版本服务的客户端。但是由于服务提供商所提供的服务常常是最新版本,因此对前向兼容性有要求的情况很少出现。另外一点是,为一个服务提供前向兼容性其实并不那么容易。因为这要求软件开发人员对产品的未来方向进行非常多的假设,而且这些假设不能有错误。反过来,这种对服务的前向兼容性的要求主要由客户端自身通过保持后向兼容性来完成。

性能

  接下来我们就来简单地说说基于HTTP的REST服务中的性能问题。在基于HTTP的REST服务中,性能提升主要分为两个方面:REST架构本身在提高性能方面做出的努力,以及基于HTTP协议的优化。

  首先要讨论的就是对登陆性能的优化。在前面我们已经介绍过,在一个基于HTTP的REST服务中,每次都将用户的用户名和密码发送到服务端并由服务端验证这些信息是否合法是一个非常消耗资源的流程。因此我们常常需要在登陆服务中使用一个缓存,或者是使用第三方单点登陆(SSO)类库。

  除此之外,软件开发人员还可以通过为同一个资源提供不同的表现形式来减少在网络上传输的数据量,从而提高REST服务的性能。

  而在集群内部服务之间,我们则可以不再使用JSON,XML等这种用户可以读懂的负载格式,而是使用二进制格式。这样可以大大地减少内部网络所需要传输的数据量。这在内部网络交换数据频繁并且所传输的数据量巨大时较为有效。

  接下来就是REST系统的横向扩展。在REST的无状态约束的支持下,我们可以很容易地向REST系统中添加一个新的服务器。

  除了这些和REST架构本身相关的性能提升之外,我们还可以在如何更高效地使用HTTP协议上努力。一个最常见的方法就是使用条件请求(Conditional Request)。简单地说,我们可以使用如下的HTTP头来有条件地存取资源:

  1. ETag:一个对用户不透明的用来标示资源实例的哈希值
  2. Data-Modified:资源被更改的时间
  3. If-Modified-Since:根据资源的更改时间有条件地Get资源。这将允许客户端对未更改的资源使用本地缓存。
  4. If-None-Match:根据ETag的值有条件地Get资源。
  5. If-Unmodified-Since:根据资源的更改时间有条件地Put或Delete资源。
  6. If-Match:根据ETag的值有条件地Put或Delete资源。

  当然,这里所提到的一系列性能优化方案实际上仅仅是比较常见的,与基于HTTP的REST服务关联较大的方案。只是顾虑到过多地陈述和REST关联不大的话题一方面显得比较没有效率,另一方面也是因为通过写另一个系列博客可以将问题陈述得更加清楚,因此在这里我们将不再继续讨论性能相关的话题。

相关资源

AtomPub:http://atomenabled.org/。其是最为广泛讨论的并借鉴的RESTful服务。其由众多HTTP和REST专家所编写,甚至包括Roy Fielding本人也参与于其中

Roy Fielding的REST论文:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

Roy Fielding的个人网站:http://roy.gbiv.com/untangled/

RFC列表:http://www.ietf.org/rfc/

时间: 2024-10-10 05:52:14

restful架构风格设计准则(六)版本管理的相关文章

restful架构风格设计准则(四)资源识别的注意事项

一.资源表示使用 单数 vs. 复数 如果一个URL所对应的资源是使用复数表示的,那么该类型的资源可能有多个.对该URL发送Get请求可能返回该资源的一个列表.如果一个URL所对应的资源是使用单数表示的,那么该类型的资源将只有一个,对该URL发送Get请求将只返回该资源的一个实例. 举例来说,一个网站所售卖的商品可能有多种类别,因此需要在URL中使用复数形式:/API/categories.对于一个该网站的用户只有一个个人偏好设置,因此其URL则需要使用单数形式:/API/users/{user

restful架构风格设计准则(三)资源识别和资源设计

restful风格的设计中,首先要识别系统中的资源,然后用HTTP规范表示这些资源. 一.资源识别 1.以资源为中心 vs 以动作为中心 以动作为中心 在传统的软件分析设计中,常常要分析业务要使用的业务逻辑,并为业务逻辑的执行提供一系列接口.如:将商品放入购物车,提交订单等.这一系列接口组合在一起就可以组成完成目标所需要执行的业务逻辑. 在需要调用这些接口的时候,软件开发人员需要向这些接口所在的URL发送一个请求,从而驱使服务执行该动作. 以资源为中心 而在restful风格的软件分析设计中,我

restful架构风格设计准则(五)用户认证和session管理

读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者! Authentication 其实在上一节中,我们已经提出了无状态约束给REST实现带来的麻烦:用户的状态是需要全部保存在客户端的.当用户需要执行某个操作的时候,其需要将所有的执行该请求所需要的信息添加到请求中.该请求将可能被REST服务集群中的任意服务器处理,而不需要担心该服务器中是否存有用户相关的状态. 但是在现有的各种基于HTTP的Web服务中,我们常常使用会话来

学习RESTFul架构

一.RESTFul介绍 1.一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序.它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一.在目前主流的三种Web服务交互方案中,R

理解RESTful 架构

REST是所有Web应用都应该遵守的架构设计指导原则. Representational State Transfer,翻译是"表现层状态转化". 面向资源是REST最明显的特征,对于同一个资源的一组不同的操作.资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词.REST要求,必须通过统一的接口来对资源执行各种操作.对于每个资源只能执行一组有限的操作.(7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS) 什么是

理解RESTful架构

越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高并发等特点. 网站开发,完全可以采用软件开发的模式.但是传统上,软件和网络是两个不同的领域,很少有交集:软件开发主要针对单机环境,网络则主要研究系统之间的通信.互联网的兴起,使得这两个领域开始融合,现在我们必须考虑,如何开发在互联网环境中使用的软件. RESTful架构,就是目前最流行的一种互联网软件架构.它

RESTful架构详解

1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一. 他在论文中提到:“我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强.性能好.适宜通信的架构.REST指的是一组架构约束条件和原则.” 如果一个架构符合REST的约束条件

RESTful架构详解(转)

1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一. 他在论文中提到:“我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强.性能好.适宜通信的架构.REST指的是一组架构约束条件和原则.” 如果一个架构符合REST的约束条件

理解RESTful架构(转载)

本文转载自:http://www.ruanyifeng.com/blog/2011/09/restful.html 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高并发等特点. 网站开发,完全可以采用软件开发的模式.但是传统上,软件和网络是两个不同的领域,很少有交集:软件开发主要针对单机环境,网络则主要研究系统之间的通信.互联网的兴起,使得这两个领域开始融