NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

与 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:218834
用户头像

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

关注

评论

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

BuildPacks 打包

Zhang

Docker image CNB OCI

重构你的css吧!(初看)

云小梦

CSS bem elementUI scss ITCSS

Go- switch-case结构

HelloBug

Go 语言 switch case

Agora 教程丨一个典型案例,教你如何使用水晶球“数据洞察”

声网

Agora 教程 水晶球

云与AI真的能互相成就?还是最好各自独立行走?

脑极体

模块五:微博评论模块高性能高可用计算架构设计

kk

架构实战营

量化策略APP系统开发,马丁策略交易平台

13530558032

做正确的事情,而不是把事情做正确

非著名程序员

个人成长 提升认知 认知提升 8月日更

Go- 函数返回值

HelloBug

函数 返回值 Go 语言

Tron波场链智能合约系统开发案例|波场链源码搭建

Geek_23f0c3

TRONex波场智能合约 DAPP智能合约交易系统开发 波场DAPP

亚信数据库AIDB通过统信UOS认证,国产自主可控项目新选择

亚信AntDB数据库

国产化 国产数据库 亚信数据库AIDB

项目进度经常超时怎么办?项目经理如何有效管理项目进度?

优秀

项目管理工具

干货!DataPipeline2021数据管理与创新大会全篇划重点

DataPipeline数见科技

大数据 数据融合 数据管理

docker概念很乱?俺来替你理一下!

Java Docker 架构 后端

快手基于 Flink 构建实时数仓场景化实践

阿里云大数据AI技术

跨团队项目的集成测试实践分享

PingCode研发中心

软件测试 测试

再也不怕 JavaScript 报错了,怎么看怎么处理都在这

前端依依

学习 技术 大前端 js

Go- break和continue

HelloBug

Go 语言 break continue

Socket 通信原理

一个大红包

8月日更

Go- goto和label

HelloBug

Go 语言 goto label

阿里巴巴最新产物!Spring+SpringBoot+SpringCloud Alibaba全系列高阶笔记

Java spring 程序员 架构 后端

上游思维:凭一己之力能做些什么?

石云升

读书笔记 8月日更 上游思维

最好用的 Angular 甘特图组件 ngx-gantt

PingCode研发中心

软件 工具 甘特图 ngx-gantt

Vue进阶(五十九):ES数组操作:splice() 实现数组删除、替换、增加指定元素

No Silver Bullet

Vue 8月日更 splice

Go- for循环

HelloBug

for Go 语言

适女化科技(一):伪需求,真消费

脑极体

InnoDB 表空间

leonsh

MySQL innodb 表空间

英特尔CEO帕特·基辛格:面向未来的数字化需求,推进未来计算创新、探索与颠覆

科技新消息

Python代码阅读(第16篇):列表求差集

Felix

Python 编程 Code Programing 阅读代码

ipfs矿机公司哪家好?ipfs矿机公司实力排行?

分布式存储 Filecoin ipfs挖矿 ipfs矿机 ipfs矿商排名

火爆 GitHub!这个图像分割神器开源了

百度开发者中心

人工智能 开源 最佳实践 图像

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