rest - 如何管理版本化 API 的底层代码库?

标签 rest versioning api-versioning

我一直在阅读 ReST API 的版本控制策略,但它们似乎都没有解决如何管理底层代码库的问题。

假设我们正在对 API 进行一系列重大更改 - 例如,更改我们的客户资源,以便它返回单独的 forenamesurname 字段,而不是单个 name 字段。 (对于此示例,我将使用 URL 版本控制解决方案,因为它很容易理解所涉及的概念,但该问题同样适用于内容协商或自定义 HTTP header )

我们现在有一个端点位于 http://api.mycompany.com/v1/customers/{id},另一个不兼容的端点位于 http://api.mycompany。 com/v2/customers/{id}。我们仍在发布 v1 API 的错误修复和安全更新,但新功能开发现在全部集中在 v2 上。我们如何编写、测试和部署对 API 服务器的更改?我至少可以看到两种解决方案:

  • 对 v1 代码库使用源代码控制分支/标签。 v1 和 v2 是独立开发和部署的,并根据需要使用修订控制合并来将相同的错误修复应用于两个版本 - 类似于在开发主要新版本同时仍然支持先前版本时管理 native 应用程序代码库的方式。

  • 使代码库本身了解 API 版本,这样您最终会得到一个包含 v1 客户表示和 v2 客户表示的单一代码库。将版本控制视为解决方案架构的一部分,而不是部署问题 - 可能使用命名空间和路由的某种组合来确保请求由正确的版本处理。

分支模型的明显优点是删除旧的 API 版本很简单 - 只需停止部署适当的分支/标签即可 - 但如果您正在运行多个版本,则最终可能会得到非常复杂的分支结构和部署管道。 “统一代码库”模型避免了这个问题,但是(我认为?)当不再需要已弃用的资源和端点时,从代码库中删除它们会变得更加困难。我知道这可能是主观的,因为不太可能有一个简单的正确答案,但我很想了解跨多个版本维护复杂 API 的组织如何解决这个问题。

最佳答案

我已经使用了你提到的两种策略。在这两种方法中,我更喜欢第二种方法,在支持它的用例中更简单。也就是说,如果版本控制需求很简单,那么就采用更简单的软件设计:

  • 变更次数少、变更复杂度低或变更频率低
  • 在很大程度上与代码库的其余部分正交的更改:公共(public) API 可以与堆栈的其余部分和平共处,而不需要在代码中进行“过多”(无论您选择采用该术语的定义)分支<

我没有发现使用此模型删除已弃用的版本过于困难:

  • 良好的测试覆盖率意味着删除已退役的 API 和相关的支持代码可以确保不会(嗯,最小的)回归
  • 良好的命名策略(API 版本的包名称,或者有点难看的方法名称中的 API 版本)可以轻松找到相关代码
  • 跨领域关注点更加困难;必须非常仔细地权衡对核心后端系统进行修改以支持多个 API。在某些时候,版本控制后端的成本(请参阅上面对“过度”的评论)超过了单个代码库的好处。

从减少共存版本之间冲突的角度来看,第一种方法当然更简单,但维护单独系统的开销往往超过减少版本冲突的好处。也就是说,建立一个新的公共(public) API 堆栈并开始在单独的 API 分支上进行迭代非常简单。当然,代际损失几乎立即出现,分支变成了困惑的合并、合并冲突解决方案以及其他类似的乐趣。

第三种方法是在架构层:采用 Facade 模式的变体,并将您的 API 抽象为面向公众的版本化层,这些层与适当的 Facade 实例对话,而 Facade 实例又通过自己的一组与后端对话。蜜蜂。您的 Facade(我在之前的项目中使用了适配器)成为其自己的包,独立且可测试,并允许您独立于后端以及相互独立地迁移前端 API。

如果您的 API 版本倾向于公开相同类型的资源,但具有不同的结构表示形式(如您的全名/名字/姓氏示例),则这将起作用。如果他们开始依赖不同的后端计算,事情会变得稍微困难​​一些,例如,“我的后端服务返回了错误计算的复利,该复利已在公共(public) API v1 中公开。我们的客户已经修补了这个不正确的行为。因此,我无法更新它计算在后端进行,并一直应用到 v2。因此,我们现在需要 fork 我们的利息计算代码。”幸运的是,这种情况往往并不常见:实际上,RESTful API 的使用者更喜欢准确的资源表示,而不是逐个错误的向后兼容性,即使是在理论上幂等 GET 资源上进行的非破坏性更改中也是如此。/p>

我很想听听您的最终决定。

关于rest - 如何管理版本化 API 的底层代码库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29871744/

相关文章:

java - 如何在REST服务启动时连接MySql数据库?

c# - 将 json 数组反序列化为 c# 列表对象

java - RestAssured 外部文件日志记录

java - 升级已发布的 Android App 的 minSdk

node.js - nvm vs 海军vs n |包处理比较

ios - 框架上的 Xcode 版本控制build设置

java - 使用 : JAX-RS API, ServiceLocator 和远程 EJB 组织我的项目的选项

ios - 带有 Indy 或第三方 Internet 组件的 iOS 上的 Delphi XE2

spring - 进行微服务 REST API 版本控制的最佳方法是什么?

java - 如何解决API版本相关障碍