写点什么

与 Roy Fielding 谈论版本化、超媒体以及 REST

  • 2015-02-05
  • 本文字数:4856 字

    阅读完需:约 16 分钟

为 Web__ 设计、实现和维护 API__ 不仅仅是一项挑战;对很多公司来说,这是一项势在必行的任务。本系列 将带领读者走过一段旅程,从为API__ 确定业务用例到设计方法论,解决实现难题,并从长远的角度看待在Web__ 上维护公共API _。沿途将会有对有影响力的人物的访谈,甚至还有 API__ 及相关主题的推荐阅读清单。_

这篇 InfoQ 文章是 Web API从开始到结束系列文章中的一篇。你可以在这里进行订阅,以便能在有新文章发布时收到通知。

Roy T. Fielding 是来自于 Adobe 的一位高级首席科学家,也是全世界促进网络软件的主要推动力之一。当他还是一位即将毕业于加利福尼亚大学尔湾分校(UCI)的学生时,他在所参与的一个课堂项目中创建了一个对 Web 进行维护的机器人,名为 MOMSpider 。其间,他还抽空创建了 libwww-perl 这一类库,其中的一些底层原则也在之后成为了 WWW 的架构的一部分。当时,Fielding 为这一部分原则命名为 _HTTP__ 对象模型 _(HTTP Object Model)。若干年之后,在他进行博士毕业论文设计的时候,他将这一模型重新命名为_ 具象状态传输_,或简称REST。它为我们展现了“一个设计良好的Web 应用程序的行为的多种特征”。

Fielding 对于开放标准做出了各个方面的巨大贡献,他的名字也总是出现在各种 RFC 规格说明中,包括 HTTP URI 模板等等。Fielding 同时还是 W3C 组织定义的“不要跟踪”请求标准的编辑之一。此外,作为 Apache HTTP 服务器项目的创始人之一,他还协助创建了这一世界上最流行的 Web 服务器软件、编写了 Apache 授权协议、成立了 Apache 软件基金会,并担任了该基金会的第一任主席。

最近,Roy 正辗转于各个有关于标准的会议之间,在此期间,他抽空回答了对于某一个经常引起争论的主题的一系列问题,这一主题就是 Web 的版本化。他也解释了为什么在他所定义的 REST 风格中,超媒体是必不可少的、设计一个能够适应未来变化的网络软件的过程、以及在设计能够在几十年之后继续可用的软件时会遇到的种种挑战等等。

InfoQ**:在 2013年 8月,你在 Adobe Evolve大会上举办了一场演讲,在演讲你对于如何对 Web的 API**** 进行“版本化”提供了一个建议,总结起来就是一句话:“不要版本化。”对于这项建议,你所看到的听众的反应是怎样的?**

Roy我认为与会的每个人都对此给出了积极的回应,因为大多数与会者都是我们的客户,并且非常熟悉 Adobe Experience Manager 产品的设计理念。当然,我不仅仅是对着幻灯片 _ 照本宣科 _,而是详细地解释了这一结论背后的理论。

在讨论的幻灯片发布到互联网上之后,各种声音就更多一些,某些读者误解了我对版本化的定义,还有些读者误解了更改主机名与商标(branding)的意义。我所说的版本化,是指将客户端可见的接口数量限定在某些名称内,这样一来客户端就可以对每个操作进行标记,将这些操作归于该 API 的某一版本。

不幸的是,对接口名称进行版本化,只是从 API 作者的角度而言实现了对变更的管理。这一点是对接口设计哲学的短视行为:作者渴望对 API 进行控制,而忽略了客户对于良好的持续性的需求。

InfoQ:那么,如果你为某个 API实现了版本化,会发生什么事呢?

Roy有以下两种可能,(a) 版本最终产生了变更,所有为之前版本所设计的组件不得不重启、重新部署、甚至于被完全抛弃,因为这些组件无法适应新系统所带来的好处。(b) 版本永远不会产生变化,就像一个永远不动的吊锤一样,它导致的结果是每个 API 调用都显得低效。

许多开发者对此举手表达他们的厌恶之情,并且坚持声称我不理解他们所遇到的问题:他们的系统非常重要、他们要对系统进行变更、要加入新的特性、数据也要进行重新组织。他们需要某种方式,让旧版本的客户端能够和新版本的客户端共存。

一般来说,遇到这种问题,我总需要解释一下,为什么“超媒体即应用状态引擎”是 REST 中不可缺少的一环。它不是可选的,也不是“最好能有”的,而且必须的。换句话说,如果你放弃这一点,就等于放弃了 REST。如果客户端将 API 的可控性寄托于部署方案的设计,那你是不可能让 API 保持逐步演化的。对于 API 的可控性必须在运行过程中进行学习,这一点正是超媒体所实现的功能。

但是,仅仅通过使用超媒体还是不足以实现逐步演化的目标。超媒体允许应用程序按需提供控制行为,但我们还需要能够让客户端理解它的表现形式的能力(对媒体类型及其所预期的处理过程的理解)。这一点是按需实现代码的闪光点。

InfoQ:如此说来,超媒体作为 REST风格不可缺少的一部分的原因之一,就在于它能够随着时间的推移对变更进行处理,是这样吗?

Roy对于变更的预期是 REST 的核心思想之一。有经验的开发者考虑到了 API 在未来可能发生的各种变化,随之想到,对接口进行版本化正是应对这些变更的正确方法,这也不是不能理解。但随之而来的问题是,在何处、以及怎样对 API 进行版本化,这方面的争论永远也不会停止。

某些开发者在内部软件的管理过程中学到了一些经验,他们相信能够控制客户端及服务器的部署,这是可以理解的。但对于那些志在跨越多个组织的界限的互联网软件来说,对于客户端及服务器的部署的完全控制则是不可能的。而这正是 REST 试图解决的问题:如何在不破坏或替换已部署的组件的情况下,对系统进行无痛升级。

因此,我的幻灯片试图将人们的注意力转回正确的方向:逐步演化的能力。换句话说,不要总想着将 API 设计为 RESTful 的,而是要想着设计一套有着你所需要的各种特性的 API。REST 的作用在于它能够引导出这些对于为多个组织服务的系统具有重要意义的特性,例如演化能力。演化能力意味着系统在适应新的变更时,无需进行重启或重新部署。

InfoQ:这是不是意味着,只要我使用 REST风格,我就不会遇到版本化所带来的问题?

Roy并非如此。总是会有某些原因,会促进你设计一套完全不同的 API,尤其是当接口的语义产生变化、或是由于安全性的原因会要求你抛弃之前所部署的软件。我的观点是,不要用版本 ID 来定义一次天翻地覆的大改动,而是用主机名来处理。因为你所创建的不是一个 API 的新版本,而是一个带有新商标的新系统。

在 Web 上,这种新系统就是指一个全新的网站。网站上不会存在任何版本号,因为它们根本不需要。RESTful API 同样也不需要版本号,一个(正确设计的)RESTful API 对于客户端来说就是一个网站,只是它的受众相对有限而已。

InfoQ**:在你的讲座中,当你讲到你所定义的 REST架构风格时,你提到 REST的设计能够支持“几十后的软件工程的规模”。从实质性的角度来说,你所说的“几十年后的规模”是指什么?**

Roy我在最初创建 REST 的时候,是为了解决我当时所遇到的一个问题:如何在不破坏 Web 的情况下改善 HTTP。在 1994-95 年那段时间,我正在重新 HTTP 协议,这是我遇到的一个重要的问题。当时我还是一位软件工程方面的博士后学生,我试图不要破坏在那个年代中已成为标准的一些东西,这就意味着我必须设计出一个能够应对今后几十年中全世界的人们所进行的各种变更。想象一下,在 1994 年创建的软件系统,有多少个延用至今的?我的意思正如字面所说:让系统在几十年后依然能够发挥作用,同时保证系统在独立且正交的方向进行演化,而不需要对系统进行关机或是重新部署。目前为止,已经过了两十年了。

InfoQ:你自己也承认,这种水平的软件工程是大多数架构师、设计师和开发者无法做到的,那么为什么还要讨论这种级别的软件工程规模呢?

Roy我之所以谈到这一点,是因为人们对于使用 REST 进行机器与机器之间通信这一方式的第一反应往往是,“既然客户端知道要发送的内容,为什么还要使用超媒体呢?它只会降低交互的速度。”这套系统设计的理念是通过解耦实现演化能力,而对于那些将“让系统在下周之内运行”,或是“我们会在下次发布中解决问题”视为金科玉律的开发者来说,他们显然无法理解这一理念。

如果开发者们期望让他们的系统运行得更长久,他们就能够从“为什么要让系统随着时间推移进行变更”的偏见中跳出来。这时我们可以将时间跨度从几十年缩短到几年(在这段时间内,你的用户群已经截然不同了),甚至缩短到几个月(在这段时间内,你还能够控制客户端的部署吗?)。

InfoQ**:HTTP这一应用层的协议通常被视为一个能够适应几十年变化的软件工程的成功案例。如今,HTTP已经发布了若干版本,而较早的 HTTP版本中存在着大量的 **错误 **,例如 Host头,绝对时间的缓存指令等等问题。这一点与你对于 Web API**所建议的“不要版本化”是否存在矛盾。

Roy不,HTTP 不会对接口名称进行版本化,在接口方法或 URI 中也不存在版本号。但不意味着通迅的其它方面不存在版本化。我们需要变更,否则我们将无法随着时间推移而改进。我们所看到的变更包括描述数据的定义语言。我们只是不欢迎破坏性的变更,因此,版本化更多地用于信息的变更,而不是用于契约的变更。

随便说一句。正确的说,HTTP 的设计几乎是完全没有什么错误的,只是整个世界对它的应用(也是由 HTTP 所产生的应用)发生了变化。Host 这一头信息在 1992 年看来是个愚蠢的设计,因为没有人需要为某个 IP 地址指定多个域名,但业务上的需求促成了它的应用。而如果 Mosaic 没有为 HTML 加入内嵌图片的功能,那么持久性连接也会成为一个糟糕的主意。绝对过期时间对于镜像托管的意义要大于缓存,而且通常来说过期时间应该是几个星期,而不是几秒种之后。

InfoQ**:那么,从 HTTP以及 HTML随着时间推移而产生了变更的这一事实中,我们又能学到些什么呢?**

Roy从 HTTP 及 HTML 中,我们所学到的是必须定义协议或语言该如何随着时间推移进行变更,以及在他们接收到某种他们还不理解的变更时应当如何进行应对。HTTP 能够随着时间进行改善的原因,是因为我们需要新的语法必须能够被忽略,并且在语义进行变更时,必须要等到新的版本能够理解新的语义才接受这种变更。

InfoQ:如今的 Web开发者面对变更的压力似乎比从前更大了。我们是否遇到了新的问题,还是说某些问题如今变得更为常见了?

Roy我认为原因只是现在的开发者遇到这种问题的机会比以前更大了。现如今,要创建一个拥有大量访问者的网站已经变得十分容易,而在从前,要让某个公司在内网之外部署一台服务器通常都要花上几年时间。在多数情况下,这是种幸福的烦恼。

软件开发者总是要与短视进行搏斗的。

InfoQ**:最后一个问题了,除了“不要版本化”之外,你对 Web API的设计者、架构师和开发者还有什么建议,能够帮助他们解决 API随时间产生变更这个问题吗?**

Roy呵呵,我可没说不要随着时间进行变更,我只是说不要在 API 中使用破坏性的名称变更。

要想给出一些通用性的建议看起来是不可能的,因为我所说的东西是特定于所创建系统的环境与类型的。我依然建议使用 REST 创建 Web 应用程序,因为它保证系统能够在未来依然运行良好,并且会带来更多的 Web 访问(更多的可访问资源)。

关于受访者

Roy T. Fielding是来自于 Adobe 的一位高级首席科学家,也是全世界促进网络软件的主要推动力之一。当他还是一位即将毕业于加利福尼亚大学尔湾分校(UCI)的学生时,他在所参与的一个课堂项目中创建了一个对 Web 进行维护的机器人,名为 MOMSpider 。其间,他还抽空创建了 libwww-perl 这一类库,其中的一些底层原则也在之后成为了 WWW 的架构的一部分。当时,Fielding 为这一部分原则命名为 HTTP 对象模型(Object Model)。若干年之后,在他进行博士毕业论文设计的时候,他将这一模型重新命名为_ 具象状态传输_,或简称REST。它为我们展现了“一个设计良好的Web 应用程序的行为的多种特征”。

为Web__ 设计、实现和维护API__ 不仅仅是一项挑战;对很多公司来说,这是一项势在必行的任务。本系列 将带领读者走过一段旅程,从为API__ 确定业务用例到设计方法论,解决实现难题,并从长远的角度看待在Web__ 上维护公共API _。沿途将会有对有影响力的人物的访谈,甚至还有 API__ 及相关主题的推荐阅读清单。_

这篇 InfoQ 文章是 Web API从开始到结束系列文章中的一篇。你可以在这里进行订阅,以便能在有新文章发布时收到通知。

查看英文原文: Article: Roy Fielding on Versioning, Hypermedia, and REST

2015-02-05 02:219197
用户头像

发布了 428 篇内容, 共 178.8 次阅读, 收获喜欢 38 次。

关注

评论

发布
暂无评论
发现更多内容

记一次sst文件损坏修复过程

TiDB 社区干货传送门

故障排查/诊断

O-Star | 矩阵起源2023届校招生入职啦~

MatrixOrigin

数据库 云原生 HTAP MatrixOrigin MatrixOne

Spring高手之路5——彻底掌握Bean的生命周期

砖业洋__

Spring Bean Spring Bean生命周期 @PostConstruct InitializingBean DisposableBean

一文了解电商大促系统的高可用保障思路 | 京东云技术团队

京东科技开发者

产品 高可用 研发 电商大促 企业号 7 月 PK 榜

装备制造行业数智人力应从何入手?超实用干货来了!

用友BIP

人力资源

用 Generative AI 构建企业专属的用户助手机器人

TiDB 社区干货传送门

全球LED显示屏市场机遇与挑战

Dylan

封装 芯片 LED显示屏 体育 全球

绘出「星辰大海」:华为云Astro轻应用新手指南-第二章

华为云PaaS服务小智

云计算 开发者 软件开发 华为云

日增320TB数据,从ClickHouse迁移至ByConity后,查询性能十分稳定!

字节跳动开源

大数据 开源 云原生 Clickhouse 数仓

Spring高手之路8——Spring Bean模块装配的艺术:@Import详解

砖业洋__

@Import 模块装配 Import注解 ImportSelector Spring动态装配

pump 日志错误信息疑问之你的pump 数据被gc了嘛?

TiDB 社区干货传送门

性能调优 实践案例 集群管理 TiDB 源码解读

矩阵起源通过ISO 三大体系认证!

MatrixOrigin

数据库 超融合 HTAP MatrixOrigin MatrixOne

Ui2Code+ChatGPT助力低代码搭建 | 京东云技术团队

京东科技开发者

低代码 ChatGPT 企业号 7 月 PK 榜 Ui2Code

免费又好用的MES系统——万界星空MES系统重磅来袭

万界星空科技

开源

零基础能学习Java吗,看了这篇文章你就知道!

java易二三

Spring高手之路6——Bean生命周期的扩展点:BeanPostProcessor

砖业洋__

spring ioc BeanPostProcessor Bean生命周期扩展点 后置处理器

LigaAI:从效率、度量和价值维度,成为研发团队的智能医生

LigaAI

研发管理 SaaS 研发协作平台 TO B 企业号 7 月 PK 榜

低代码技术分享官丨浅谈DevOps实践过程

inBuilder低代码平台

DevOps

阿里大牛用了一个月把Github上热度最高的Java面试八股文总结出来了,按这个学,找工作没问题

架构师之道

java面试

Centos8 stream系统编译安装Apache教程。

百度搜索:蓝易云

Apache 云计算 Linux centos 运维

Centos8 stream系统编译安装MySQL5.7教程。

百度搜索:蓝易云

MySQL 云计算 Linux centos 运维

关于互联网产业的一些思考

用友BIP

产业互联网

绘出「星辰大海」:华为云Astro轻应用新手指南-第一章

华为云PaaS服务小智

云计算 华为 开发者 华为云

7.25齐聚西安!助推国资国企建设一流司库管理体系

用友BIP

全球司库 国资国企

中移链与BSN分布式云管平台集成,共同构建专属协同体系

BSN研习社

企业数智化底座赋能国资国企数智监管

用友BIP

数智底座 国资国企

Spring高手之路4——深度解析Spring内置作用域及其在实践中的应用

砖业洋__

spring Singleton prototype Spring作用域 Spring原型作用域

抽象语法树AST必知必会 | 京东物流技术团队

京东科技开发者

前端 AST 抽象语法树 企业号 7 月 PK 榜

倒计时 1 天!21 位大咖 11个议题,龙蜥社区走进 Intel MeetUp 即将在上海召开

OpenAnolis小助手

操作系统 芯片 intel Meetup 龙蜥社区

Spring高手之路7——事件机制与监听器的全面探索

砖业洋__

spring 观察者模式 事件机制 Spring生命周期 Spring 监听

Spring高手之路9——掌握Spring条件装配的秘密武器

砖业洋__

spring Spring配置 @Profile @Conditional 条件装配

与Roy Fielding谈论版本化、超媒体以及REST_REST_Mike Amundsen_InfoQ精选文章