|
# B2 O, H7 Z& @6 Z/ l/ t3 L. V 本文最初发表于HTTP Toolkit网站,经原作者 Tim Perry 授权由 InfoQ 中文站翻译分享万物都会有终结,HTTP API 也不例外不论你的 API 今天看上去多么伟大,迟早有一天你会想发布一个全新的版本,新版本能更好地解决相同问题,在各方面可能都会有所改善,但是它因为有了新参数,与旧版本也无法兼容,或者你只是想彻底关闭旧的 API。
2 _" u% K9 _3 N+ H% Z9 J6 G 总而言之,你现在的 API 不会永远存在但是,这并非轻而易举就能完成的,因为你的 API 有客户端如果你关闭端点、参数或整个 API 而没有做出恰当的警告的话,那他们肯定会非常不爽那么,该怎样安全地关闭 API,让你的用户尽可能地感到轻松愉快呢?。
9 }) j [" J m" x5 n% e 在这方面,我们有正确的做事方式,包括两个新的头信息草案,它们正在被新的 IETF “Building Blocks for HTTP APIs”工作组进行标准化,旨在形成一个精确的过程我们了解一下制定计划
2 X7 R' z% t- W% h 初始第一步:检查相关的 API 是否真的有客户端希望你能有某些 API 的度量指标,至少在某些地方存有日志如果没有的话,那把它们添加上,如果你有这些东西的话,并且你能确定没有人再使用这个 API 了,那么恭喜你,你赢了。 ; `6 e$ ~! L+ M1 d7 c0 M/ G" I
现在,你就可以把它关掉,删掉代码,不要再管这篇文章了,好好睡一觉下一个问题,如果比较遗憾,你无法去睡觉的话,那就要问问自己,除了关闭这个 API,还有没有其他方案你关闭的所有东西都有可能破坏别人的代码,并且会消耗他们的时间来修复这些问题。 i4 ^% C+ V% _* |* Q
如果 API 能继续运行的话,对客户端的生态系统和整个 web 的健康都是有好处的在很多场景下,旧的 API 可以在内部进行转换,透明地转化成对新 API 的调用,这样可以避免维护两个完全独立的版本这是Stripe的API版本管理方式的一个基本组成部分,他们在所有发生变化的 API 中都包含了转换,以确保对不兼容的旧版本 API 的请求能继续像以前那样运行,根据需要自动转换请求和响应从而可以使用较新的代码。
; Y2 }7 o) C7 P; R0 c0 R% M) N) y) a 这样的转换并不总是可行的,而且如果永远这样做的话会带来明显的额外复杂性,但是如果你可以做到这一点的话,就能为用户提供非常有价值的稳定性,并且可以节省大量废弃旧版本或维护旧版本相关的工作但是,如果这个服务/端点/参数已经用到了生产环境,而且继续支持它是不现实的做法,那么它必须要被淘汰。
; C# y/ x7 Q; r9 K# Z 要实现这一点,我们就要有一个计划我们首先要问自己三个关键的问题:你希望用户该怎么做?常见的答案包括:升级到相关功能的一个更新的、依然能得到支持的版本使用一些可替代的端点/参数/服务使用不同的服务,它们与你无关,不需要你关心。
, `; }* O! [3 K- x, q( y 用户应该何时迁离这个 API?你所提出的替代方案现在就可以用了吗?截止时间是什么时候?也就是,这个 API 何时会完全停止使用?(如果不能完全确定的话,你可以稍微延迟回答这个问题)计划准备就绪之后,我们就该把它告诉人们了。 4 U( U. u- C& h8 [! @
沟通首先,要把这一决定告诉人们发邮件到邮件列表,在 Twitter 或微博上发帖,如果有 API 规范的话,对其进行更新(比如,OpenAPI 在operations和parameters上有一个deprecated。 , h; T& C2 k. v" N \5 _: F' r- S
字段),并在相关的在线文档上大声强调这一点你应该包含上文提到的所有信息:他们应该做些什么作为替代方案,你建议他们什么时候开始迁移以及他们必须要进行迁移的最后期限(如果已经确定期限的话)在将这些信息告诉给人们后,接下来就该告诉计算机,而这就是新的 IETF 头信息可以发挥作用的地方。
( i% Z1 ?7 R+ R: m$ T' {8 A- k Deprecation 头信息Deprecation头信息能告诉客户端请求的资源现在依然像以前那样运行,但是这种方式已经不再推荐使用了通过一个简单的 HTTP 头信息,我们就可以声明这一点:Deprecation:。 ) l& v0 v4 G# }# v
true另外,我们还能提供一个日期这个日期告诉用户他们何时该开始进行迁移这个日期可以是一个过去时间(这代表他们应该立即开始迁移),也能是将来时间(通常这意味着他们要迁移到的新环境还没有准备就绪)如下所示:。
" S6 a6 x* |' { Deprecation:Thu,21Jan202123:59:59GMT如果你要废弃整个端点或服务,那么你可以在每个响应中都带上这样的头信息如果你想要废弃的是一个具体的特性,可能是一个参数、请求方法或者请求体中的某个特定字段的话,那么你应该在该特性被使用的时候才在响应中包含这个头信息。
9 e/ |: u( \" W4 ]8 U1 V# _+ s 为了给客户端更多的信息,我们还可以使用Link HTTP 响应头信息链接至端点或人类易读的文档在同一个Link头信息中,我们可以包含多个这样的链接,只需要使用逗号进行分割即可(后面我们会看到一个完整的例子)。 ( v* U V) P, ~& D1 \ N4 \
该规范定义了四个与 API 废弃相关的链接:Deprecation 链接我们可以为 deprecation 链接指向一个人类易于阅读的描述:Link: ; rel=
. N7 m% t8 Q9 @8 c "deprecation"; type="text/html"这是告诉用户发生了什么以及他们该怎么办的主要方式你应该始终使用它如果还没有完整的详情和最终的关闭日期,那么即使只是一个占位符,这也是很有帮助的。
: [1 T; @3 Q. e5 M' g/ Q* I 在这种情况下,不要忘记让用户订阅更新,这可以采用邮件列表、RSS 或其他类似的方式来实现Latest-Version 链接如果你希望客户端转移至 API 相同端点的最新版本,那么可以使用该链接指向它,如下所示:
, P: K( g! z4 H$ H$ o" @. X Link: ; rel="latest-version"Successor-Version 链接如果你的 API 有多个可用的版本,通常最好每次向前迁移一个版本,而不是直接从最老的、现已废弃的版本跳到最新的版本。 + k2 l2 h! B* S* D2 S Y
为了帮助解决这个问题,我们链接至已废弃版本的下一个版本,而不是最新版本,如下所示:Link: ; rel="successor-version"
9 a: v8 [& G# C3 g Alternate 链接如果该 API 没有新的等价版本,用户最好迁移到一个完全不同的资源,它可能是一个很好的替代方案,那么我们使用 alternate 链接来指明这一点,如下所示:Link:
: [8 g3 H3 C# {$ |/ x //api.example.com/v2/users/123/clients>; rel="alternate"Sunset 头信息如果你知道了 API 何时完全关闭的话,那么就应该添加一个Sunset头信息。 2 d+ y; e0 A5 z& h
Sunset 头信息告诉客户端 API 何时会停止运行这是一个强制的截止时间:API 客户端必须要在这个日期前进行迁移,我们承诺在这个时间前不会破坏任何事情在这里,我们必须要提供一个时间,它应该是一个未来的时间。
; S+ Q e! X( x 不过,如果它是一个过去的时间,这也是可以的:此时就相当于说“这个 API 会在任意时刻关闭,你需要立即停止使用它”它如下所示:Sunset:Tue,20Jul202123:59:59GMT这非常简单,它不仅可以用到 API 关闭的场景中:我们能用它来标记将来 URL 迁移的 HTTP 重定向,或者表明特定 URL 有限的生命周期(适用于临时性的内容,或者适用于具有监管要求的特定资源,比如数据保留策略)。 2 Y0 @4 A8 ^, {1 e( `
它所说明的就是“这个端点可能在该日期后不会再按照你的预期运行,请做好准备”Sunset 链接该规范也提供了一个 Sunset 链接的关系按照设计,它会链接至关于关闭特定端点更加详细的信息(如果你有 deprecation 链接的话,它们可能会是同一个)或者关于服务的通用 Sunset 策略。 % O. `, E. S ^
如下所示:Link: ;rel="sunset";type="text/html"在这里我们也要指出,通用的 Sunset 策略是非常有用的!Sunset 策略会告诉客户端,当我们关闭端点的时候(比如,一年后替代方案上线),用户该如何确保他们能得知这一情况(邮件列表、状态页面、HTTP 头信息等)以及他们通常应该做些什么(更新、检查文档、遵从 7 {$ P) a+ ~ m( Q! P$ v9 i9 u
Link头信息)如果马上就要废弃某个 API 的话,添加这样的链接作用其实不大,但是如果你能在一年前就将其发布出去的话,你的客户端可能已经为此做好了准备除此之外,发布 Sunset/Deprecation 策略的最好时间就是现在。 ( \$ x9 F8 C4 P0 e. `! \
如果你恰好正以某种方式编写 Deprecation 文档的话,这么做是值得考虑的组合到一起按照设计,这些组成部分能很好地协作例如,为了表明某个最近废弃的 API,该 API 会在 6 个月内彻底关闭,我们要链接至文档并提供下一个版本的直接链接,那么我们应该在响应中包含如下的头信息链接:。 / V& F2 y3 s9 p& J! @. U" G+ C
Deprecation:Thu,21Jan202123:59:59GMTSunset:Tue,20Jul202123:59:59GMTLink:; : H+ p; l6 u" d- l! r8 E; B7 `
rel="successor-version",;rel="deprecation"渐进式关闭 / P5 a2 a9 Q. ]8 C
如果所有这些都已经准备到位,并且 sunset 截止时间已过,那么我们就可以将 API 关闭了但是,这并不意味着你需要立即且彻底消灭该 API渐进式关闭能有助于确保任何使用该 API 的所有客户端都有最后的机会在它彻底消失前得到最后一次警告。
) m, V& f3 Z3 T* c5 I% ` x GitHub 在 2018 年移除一些加密支持的时候曾经这样做:首先禁用一个小时,然后启用它,最后在两周后彻底禁用了它这里还有另外一个技巧:安卓在 2015 年为已废弃的原生API增加了越来越多的延迟,在彻底关闭 API 前,最终达到了 16 秒的等待。 0 H% F& n8 L z2 `( {
这些渐进式的关闭为那些错过截止日期的客户端提供了一些灵活性,并且能帮助那些没有注意到废弃时间点的客户端,从而能在 API 彻底关闭之前处理一些问题谨慎行事不管采用哪种方式,只要你尽了最大的努力去沟通关于 API 关闭的事情,那么现在就可以关闭端点/特性/整个服务,删除代码,然后睡个好觉。 $ i: b T7 K- f$ X n, h
像这样小心谨慎地进行废弃和关闭,可以让你的客户端尽可能清楚地知道他们该如何依赖你的 API,何时需要采取行动,以及他们需要做什么这种变更可能是一件大事儿,这些信息是很重要的这些新的草案头信息让我们不仅可以与人类沟通,还能将这些信息暴露给自动化系统。 7 `! x1 P: [1 j% P
随着这些头信息的普及,我很高兴地开始看到有更多的工具建立在它们之上通用的 HTTP 客户端可以根据这些数据自动记录有用的警告日志,API 生成器本身也能根据 API 规范处理越来越多的问题,而 HTTP 调试器(如HTTP Toolkit)可以在截获的实时流量中为你突出显示废弃端点的使用。 ' X' J$ P1 D( g" J
这是一个令人激动的时刻,我们可以开始安全地关闭 API 了!需要注意的是,这些头信息是 HTTP 规范的草案在最终确定前,它们有可能会发生变化也就是说,它们经历了几轮修改,从现在开始,它们不太可能发生巨大的变化,现在能广泛测试它们了。
6 W4 R( ~0 f9 U 不过这也意味着还有时间进行反馈! 如果你对它们的工作方式和如何更好地运行有想法的话,请与“Building Blocks for HTTP APIs”工作组联系你可以给邮件列表发邮件:httpapi@ietf.org,或者在这里查看之前的邮件列表讨论。 $ d' [7 m# f' `
原文链接:https://httptoolkit.tech/blog/how-to-turn-off-your-old-apis/
7 o ^( w6 j& W* @
+ P) `/ k" g5 {" q( A, u% r
$ n6 Y3 d9 m( g* i- D" \# b2 _6 V( _7 ~. R5 {
9 C0 c% Y: ]6 I2 [
|