Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

RESTful API 版本控制最佳实践:为什么 v1 是第一

电子邮件

1 min read

RESTful API 版本控制最佳实践:为什么 v1 是第一

电子邮件

1 min read

RESTful API 版本控制最佳实践:为什么 v1 是第一

那么,给一个API版本化有多难呢?真相是这并不难,但困难在于保持某种理智,而不是不必要地陷入数量繁多、相互不兼容的版本和子版本中,这些版本和子版本应用于数十个API端点。

重大变化不好!API版本控制好!

任何曾经构建或经常使用API的人迟早都会意识到,重大变化非常糟糕,可能会对一个本来有用的API造成非常严重的瑕疵。重大变化是指对API行为的改变,可能会破坏用户的集成,并导致API提供者与用户之间的许多挫折感和信任丧失。重大变化要求用户提前通知(并伴随致歉),而不是像令人愉悦的新功能那样突然出现。避免这种挫折的方法是通过API所有者的保证为API制定版本,以确保任何单一版本中不会引入令人惊讶的变化。




那么,给一个API制定版本有多难呢?事实上并不难,但难的是在不必要地陷入令人头晕的版本和子版本数量中保持理智,这些版本和子版本应用于几十个API端点,上面的兼容性不明确。




我们在三年前推出了API的v1,并没有意识到它能够一直保持至今。那么,我们在两年多的时间里如何继续提供最佳的电子邮件传送API,同时保持相同的API版本呢?虽然关于如何给REST API制定版本有很多不同的观点,但我希望我们谦逊而强大的v1的故事能够在您的API版本化启蒙之路上指引您。

REST Is Best

SparkPost API 起源于我们还是 Message Systems 的时候,在我们开始云中的冒险之前。当时我们正忙于为 Momentum 4 的测试版发布做最后准备。这是对市场领先的本地部署 MTA 版本 3.x 的重大升级。Momentum 4 包括一个全新的 UI、实时分析以及最重要的新 Web API,用于消息注入和生成、管理模板和获取电子邮件指标。我们的愿景是 API 优先架构——甚至 UI 都会与 API 端点进行交互。




我们做出的最早且最佳决策之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现层状态转换 (REST) 的 Web API 已成为云 API 的事实标准。使用 HTTP 和 JSON 使得开发人员可以轻松集成我们的 API,无论他们使用哪种编程语言——PHP、Ruby 和 Java——都不需要了解或关心我们的底层技术。




选择使用 RESTful 架构很容易。选择版本控制约定并不那么容易。最初我们在版本控制问题上采取了回避策略,没有对测试版进行版本控制。然而,在发布几个月内,测试版已经交到少数客户手中,我们开始构建我们的云服务。时间到了进行版本控制。我们评估了两种版本控制约定。第一种是在 URI 中直接放置版本控制,第二种是使用 Accept 头。第一种选择更加明确且不复杂,这对开发者更容易。由于我们爱开发者,这是合乎逻辑的选择。

SparkPost API 起源于我们还是 Message Systems 的时候,在我们开始云中的冒险之前。当时我们正忙于为 Momentum 4 的测试版发布做最后准备。这是对市场领先的本地部署 MTA 版本 3.x 的重大升级。Momentum 4 包括一个全新的 UI、实时分析以及最重要的新 Web API,用于消息注入和生成、管理模板和获取电子邮件指标。我们的愿景是 API 优先架构——甚至 UI 都会与 API 端点进行交互。




我们做出的最早且最佳决策之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现层状态转换 (REST) 的 Web API 已成为云 API 的事实标准。使用 HTTP 和 JSON 使得开发人员可以轻松集成我们的 API,无论他们使用哪种编程语言——PHP、Ruby 和 Java——都不需要了解或关心我们的底层技术。




选择使用 RESTful 架构很容易。选择版本控制约定并不那么容易。最初我们在版本控制问题上采取了回避策略,没有对测试版进行版本控制。然而,在发布几个月内,测试版已经交到少数客户手中,我们开始构建我们的云服务。时间到了进行版本控制。我们评估了两种版本控制约定。第一种是在 URI 中直接放置版本控制,第二种是使用 Accept 头。第一种选择更加明确且不复杂,这对开发者更容易。由于我们爱开发者,这是合乎逻辑的选择。

SparkPost API 起源于我们还是 Message Systems 的时候,在我们开始云中的冒险之前。当时我们正忙于为 Momentum 4 的测试版发布做最后准备。这是对市场领先的本地部署 MTA 版本 3.x 的重大升级。Momentum 4 包括一个全新的 UI、实时分析以及最重要的新 Web API,用于消息注入和生成、管理模板和获取电子邮件指标。我们的愿景是 API 优先架构——甚至 UI 都会与 API 端点进行交互。




我们做出的最早且最佳决策之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现层状态转换 (REST) 的 Web API 已成为云 API 的事实标准。使用 HTTP 和 JSON 使得开发人员可以轻松集成我们的 API,无论他们使用哪种编程语言——PHP、Ruby 和 Java——都不需要了解或关心我们的底层技术。




选择使用 RESTful 架构很容易。选择版本控制约定并不那么容易。最初我们在版本控制问题上采取了回避策略,没有对测试版进行版本控制。然而,在发布几个月内,测试版已经交到少数客户手中,我们开始构建我们的云服务。时间到了进行版本控制。我们评估了两种版本控制约定。第一种是在 URI 中直接放置版本控制,第二种是使用 Accept 头。第一种选择更加明确且不复杂,这对开发者更容易。由于我们爱开发者,这是合乎逻辑的选择。

API 管理

选择版本控制约定后,我们又有了更多问题。何时应该提升版本号?什么是重大更改?我们是重新版本化整个 API 还是只是某些端点?在 SparkPost,我们有多个团队在不同部分的 API 上工作。在这些团队中,人们在不同时间处理不同端点。因此,确保我们的 API 在使用约定时保持一致性非常重要。这超越了版本控制的范畴。




我们成立了一个治理小组,包括代表每个团队的工程师、产品管理团队的一名成员以及我们的 CTO。这个小组负责在所有团队中建立、记录并执行我们的 API 约定。一个 API 治理 Slack 频道对于就此话题进行生动的辩论也很有帮助。




治理小组确定了多种可以引入 API 的更改,既对用户有利又不构成重大更改。这些包括:




  • 新的资源或 API 端点

  • 新的可选参数

  • 对非公开 API 端点的更改

  • JSON POST 主体中的新可选键

  • JSON 响应主体中返回的新键




相反,重大更改包括任何可能破坏用户集成的内容,例如:




  • 新的必需参数

  • POST 主体中的新的必需键

  • 现有端点的移除

  • 现有端点请求方法的移除

  • API 调用的实质性不同的内部行为,例如默认行为的更改。

The Big 1.0

当我们记录和讨论这些约定时,我们也得出结论,避免对API进行重大更改符合每个人(包括我们自己!)的最佳利益,因为管理多个版本会增加相当多的开销。我们决定在承诺“v1”之前,有一些我们应该修复的API问题。




发送简单的电子邮件需要过多的努力。为了“保持简单事物的简单”,我们更新了POST主体,以确保既适合简单的又复杂的用例。新的格式在未来也更加可靠。其次,我们解决了Metrics端点的问题。该端点使用了一个“group_by”参数,该参数会更改GET响应主体的格式,使得第一个键是group by参数的值。这看起来不太像RESTful,所以我们将每个group by拆分成一个单独的端点。最后,我们审核了每个端点,并在各处做了一些小改动,以确保它们符合标准。

准确的Documentation

拥有准确且可用的 API 文档很重要,以避免有意或无意的重大更改。我们决定使用一种简单的 API 文档方法,利用一种名为 API Blueprint的Markdown语言,并在Github上管理我们的文档。我们的社区参与协作并改进这些开源文档。同时,我们还在 Github 中维护了一套非公开的内部API和端点文档。




起初,我们将文档发布到 Apiary,这是一款用于原型设计和发布API文档的出色工具。然而,将 Apiary 嵌入我们的网站在移动设备上不起作用,因此我们现在改用Jekyll来生成静态文档。我们的最新SparkPost API 文档现在加载迅速,并在移动设备上运行良好,这对于并不总是坐在电脑前的开发者来说非常重要。

分离 Deployment 和 Release

我们很早就学到了一个宝贵的技巧,即将部署与发布分开。这样一来,当变更准备好后,可以通过持续交付和部署频繁地进行部署,但我们不总是同时公开宣布或记录这些变更。对于我们来说,在UI中或使用内部工具时,先部署一个新的API端点或对现有API端点的增强,而在公开记录和支持之前使用它,这并不罕见。这样,我们可以对其进行一些调整以提高可用性或符合标准,而不必担心造成令人害怕的重大变更。一旦我们对更改感到满意,我们就会将其添加到我们的公共文档中。

哎呀!

我们必须承认,有些时候我们未能坚持我们的“无破坏性更改”理想,这些都是值得学习的。在一次情况下,我们认为如果某个属性默认设置为 true 而非 false 会对用户更好。在我们部署更改后,由于行为发生了意外变化,我们收到了用户的几次投诉。 我们撤销了更改并增加了一个账户级别设置——这显然是更为用户友好的方法。




有时,我们会因为修复错误而想引入破坏性更改。然而,为了保持一致性,我们决定不改变这些特性,以免风险破坏客户的集成。




在极少数情况下,我们做出了重要决定去进行破坏性更改——例如弃用一个 API 资源或方法——为了更广泛用户社区的利益,并且只有在确认对用户几乎没有影响的情况下才进行。例如,我们特意选择改变 Suppression API 的响应行为,但只是在仔细权衡对社区的好处和影响,并认真与我们的用户沟通更改之后。然而,我们绝不会引入对用户的生产电子邮件发送有直接影响的更改,即使可能性极低。

加入我们的Newsletter。

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

加入我们的Newsletter。

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

加入我们的Newsletter。

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Pinterest 标志
Uber 标志
Square 徽标
Adobe 标志
Meta logo
PayPal 标志

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Uber 标志
Square 徽标
Adobe 标志
Meta logo

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Uber 标志
Adobe 标志
Meta logo

Reach

Grow

Manage

Automate

资源

公司

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。