

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Amazon API Gateway 中使用自定义域实施基于路径的 API 版本控制
<a name="implement-path-based-api-versioning-by-using-custom-domains"></a>

*Corey Schnedl、Marcelo Barbosa、Mario Lopez Martinez、Anbazhagan Ponnuswamy、 Gaurav Samudra 和 Abhilash Vinod，Amazon Web Services*

## Summary
<a name="implement-path-based-api-versioning-by-using-custom-domains-summary"></a>

此模式演示了如何使用[自定义域](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html)的 [API 映射](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html)功能，为 Amazon API Gateway 实施基于路径的 API 版本控制解决方案。

Amazon API Gateway 是一项完全托管的服务，您可以使用它来创建、发布、维护、监控和保护 APIs 任何规模。通过使用该服务的自定义域名功能，您可以创建更简单、更直观的自定义域名 URLs ，以便提供给 API 用户。您可以使用 API 映射将 API 阶段连接到自定义域名。创建域名并配置 DNS 记录后，您可以使用 API 映射 APIs 通过您的自定义域名向您发送流量。

在 API 公开可用后，使用者便会使用它。随着公有 API 的发展，为反映新的特征和功能，其服务合同也在不断演变。但是，更改或移除现有功能并非明智之举。任何重大更改都可能影响消费者的应用程序，并导致其在运行时崩溃故障。API 版本控制对于避免破坏向后兼容性和破坏合约至关重要。

您需要制定明确的 API 版本控制策略，以帮助使用者采用这些策略。使用基于路径 APIs 的版本控制 URLs 是最直接和最常用的方法。在这种版本控制中，版本被明确定义为 API URIs 的一部分。以下示例 URLs 显示消费者如何使用 URI 为其请求指定 API 版本：

`https://api.example.com/api/v1/orders `

`https://api.example.com/api/v2/orders `

`https://api.example.com/api/vX/orders`

此模式使用为您的 AWS Cloud Development Kit (AWS CDK) API 构建、部署和测试基于路径的可扩展版本控制解决方案的示例实现。 AWS CDK 是一个开源软件开发框架，用于使用熟悉的编程语言对云应用程序资源进行建模和配置。

## 先决条件和限制
<a name="implement-path-based-api-versioning-by-using-custom-domains-prereqs"></a>

**先决条件**
+ 活跃 AWS 账户的.
+ 要使用此模式的示例存储库以及使用 Amazon API Gateway 自定义域功能，需要拥有域的所有权。您可以使用 Amazon Route 53 为您的组织创建和管理您的域。有关如何使用 Route 53 注册或转移域的信息，请参阅 Route 53 文档中的[注册新域](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register-update.html)。
+ 为 API 设置自定义域名之前，您必须先在 AWS Certificate Manager中准备好 [SSL/TLS 证书](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-specify-certificate-for-custom-domain-name.html)。
+ 您必须创建或更新 DNS 提供程序的资源记录以映射到您的 API 端点。如果没有此类映射，针对自定义域名的 API 请求无法到达 API Gateway。

**限制**
+ 自定义域名在所有域名中必须是 AWS 区域 唯一的 AWS 账户。
+ 要配置具有多个级别的 API 映射，您必须使用区域自定义域名并使用 TLS 1.2 安全策略。
+ 在 API 映射中，自定义域名和映射的域名 APIs 必须相同 AWS 账户。
+ API 映射必须仅包含字母、数字和以下字符：`$-_.+!*'()/`
+ API 映射中路径的最大长度为 300 个字符。
+ 每个域名可以有 200 个具有多个级别的 API 映射。
+ 您只能使用 TLS 1.2 安全策略 APIs 将 HTTP 映射到区域自定义域名。
+ 你不能映射 WebSocket APIs 到与 HTTP API 或 REST API 相同的自定义域名。
+ 有些 AWS 服务 并非全部可用 AWS 区域。有关区域可用性，请参阅[按区域划分的AWS 服务](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)。有关特定端点，请参阅[服务端点和配额](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)，然后选择相应服务的链接。

**产品版本**
+ 此示例实现在 2.149.0 TypeScript 版本[AWS CDK 中](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)使用。

## 架构
<a name="implement-path-based-api-versioning-by-using-custom-domains-architecture"></a>

下图显示了架构工作流。

![\[使用 API 映射和自定义域实施基于路径的 API 版本控制解决方案的工作流。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/e1b32d2b-410f-4ace-967e-f0b8aaf0304c/images/fa9f04f1-efa6-4fb1-a541-ae3da4076b00.png)


下图说明了以下内容：

1. API 用户使用自定义域名向 Amazon API Gateway 发送请求。

1. API Gateway 根据请求 URL 中指示的路径，动态地将用户的请求路由到 API Gateway 的相应实例和阶段。下表显示了如何将不同的基于 URL 的路径路由到不同 API Gateway 实例的特定阶段的示例。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/implement-path-based-api-versioning-by-using-custom-domains.html)

1. 目标 API Gateway 实例处理请求并将结果返回给用户。

**自动化和扩展**

我们建议您为每个 API 版本使用单独的 AWS CloudFormation 堆栈。通过这种方法，您可以在后端之间实现完全隔离 APIs ，自定义域 API 映射功能可以路由到该后端。采用这种方法的一个优势是，可以独立部署或移除不同版本的 API，而不出现修改其他 API 的风险。这种方法通过隔离 CloudFormation 堆栈来提高弹性。此外，它还为您的 API 提供了不同的后端选项 AWS Lambda，例如、 AWS Fargate、HTTP 端点和的 AWS 服务操作。

您可以将 Git 分支策略（例如 [Gitflow](https://docs.aws.amazon.com/prescriptive-guidance/latest/choosing-git-branch-approach/gitflow-branching-strategy.html)）与隔离 CloudFormation 堆栈结合使用，来管理部署到不同版本的 API 的源代码。通过使用此选项，您可以维护不同版本的 API，而无需为新版本复制源代码。使用 Gitflow，您可以在执行发布时为 git 存储库中的提交添加标签。因此，您可以获得与特定版本相关的源代码的完整快照。由于需要执行更新，您可以查看特定版本中的代码，进行更新，然后将更新的源代码部署到与相应主版本一致的 CloudFormation 堆栈中。这种方法降低了破坏其他 API 版本的风险，因为每个 API 版本都有独立的源代码并部署到不同的 CloudFormation 堆栈中。

## 工具
<a name="implement-path-based-api-versioning-by-using-custom-domains-tools"></a>

**AWS 服务**
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 可帮助您创建、发布、维护、监控和保护任何规模的 RES WebSocket APIs T、HTTP。
+ [AWS Certificate Manager (ACM)](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) 可帮助您创建、存储和续订 X.509 公有和私有 SSL/TLS X.509 证书和密钥，以保护您的 AWS 网站和应用程序。
+ [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/v2/guide/home.html)是一个开源软件开发框架，用于在代码中定义您的云基础架构并通过它进行配置 CloudFormation。此模式的示例实现使用 [AWS CDK in TypeScript](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)。在 in AWS CDK 中 TypeScript 使用熟悉的工具，包括 Microsoft TypeScript 编译器 (`tsc`)、[Node.js](https://nodejs.org/) 和节点包管理器 (`npm`)。如果您愿意，则可以使用 [Yarn](https://yarnpkg.com/)，尽管此模式中的示例使用的是 `npm`。通过 `npm ` 存储库 [npmjs.org](https://docs.npmjs.com/) 来分发构成 [AWS 构造库](https://docs.aws.amazon.com/cdk/v2/guide/libraries.html#libraries-construct)的模块。
+ [CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)帮助您设置 AWS 资源，快速一致地配置资源，并在和的整个 AWS 账户 生命周期中对其进行管理 AWS 区域。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一项计算服务，可帮助您运行代码，无需预调配或管理服务器。它只在需要时运行您的代码，并自动进行扩展，因此您只需为使用的计算时间付费。
+ [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/Welcome.html) 是一种可用性高、可扩展性强的 DNS Web 服务。
+ [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/what-is-aws-waf.html) 是一种 Web 应用程序防火墙，可帮助您监控转发至受保护 Web 应用程序资源的 HTTP 和 HTTPS 请求。

**其他工具**
+ [Bruno](https://www.usebruno.com/) 是一种开源 Git 友好型 API 测试客户端。
+ [cdk-nag](https://github.com/cdklabs/cdk-nag) 是一个开源实用程序，它使用规则包检查 AWS CDK 应用程序的最佳实践。

**代码存储库**

此模式的代码可在 GitHub [path-based-versioning-with-api-](https://github.com/aws-samples/path-based-versioning-with-api-gateway) gateway 存储库中找到。

## 最佳实践
<a name="implement-path-based-api-versioning-by-using-custom-domains-best-practices"></a>
+ 使用强大的持续集成和持续交付 (CI/CD) 管道，自动测试和部署使用构建的 CloudFormation 堆栈。 AWS CDK有关此建议的更多信息，请参阅 Well-Architect [AWS ed 指南 DevOps 。](https://docs.aws.amazon.com/wellarchitected/latest/devops-guidance/devops-guidance.html)
+ AWS WAF 是一款托管防火墙，可轻松与 Amazon API Gateway 等服务集成。尽管 AWS WAF 这不是此版本控制模式起作用的必要组件，但我们建议将其作为安全最佳实践包含 AWS WAF 在 API Gateway 中。
+ 鼓励 API 使用者定期将 API 升级到最新版本，以便可以高效地弃用和移除旧版本的 API。
+ 在生产环境中使用此方法之前，请为您的 API 实施防火墙和授权策略。
+ 使用[最低权限访问模式实现对 AWS 资源管理的访问权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)。 AWS 账户 
+ 要对使用构建的应用程序强制执行最佳实践和安全建议 AWS CDK，我们建议您使用 [cdk-na](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/check-aws-cdk-applications-or-cloudformation-templates-for-best-practices-by-using-cdk-nag-rule-packs.html) g 实用程序。

## 操作说明
<a name="implement-path-based-api-versioning-by-using-custom-domains-epics"></a>

### 准备本地环境
<a name="prepare-your-local-environment"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 克隆存储库。 | 要克隆示例应用程序存储库，请运行以下命令：<pre>git clone https://github.com/aws-samples/path-based-versioning-with-api-gateway</pre> | 应用程序开发人员 | 
| 导航到克隆的存储库。 | 要导航到克隆的存储库文件夹位置，请运行以下命令：<pre>cd api-gateway-custom-domain-versioning</pre> | 应用程序开发人员 | 
| 安装所需的依赖项。 | 要安装所需依赖项，请运行以下命令：<pre>npm install </pre> | 应用程序开发人员 | 

### 部署 CloudFormation 路由堆栈
<a name="deploy-the-cfnshort-routing-stack"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 启动路由堆栈的部署。 | 要启动 CloudFormation 路由堆栈的部署`CustomDomainRouterStack`，请运行以下命令，`example.com`替换为您拥有的域名：<pre>npx cdk deploy CustomDomainRouterStack --parameters PrerequisiteDomainName=example.com</pre>只有成功执行以下域 DNS 验证任务，才能成功完成堆栈部署。 | 应用程序开发人员 | 

### 验证域所有权
<a name="verify-domain-ownership"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 验证域的所有权。 | 在您证明关联域的所有权之前，证书将一直处于**等待验证**状态。要证明所有权，请将 CNAME 记录添加到与该域关联的托管区。有关更多信息，请参阅 AWS Certificate Manager 文档中的 [DNS 验证](https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html)。添加适当的记录可以使 `CustomDomainRouterStack` 部署成功。 | 应用程序开发人员、AWS 系统管理员、网络管理员 | 
| 创建别名记录，以指向您的 API Gateway 自定义域。 | 成功颁发并验证证书后，[创建一条 DNS 记录](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-regional-api-custom-domain-create.html#apigateway-regional-api-custom-domain-dns-record)，该记录可指向您的 Amazon API Gateway 自定义域 URL。自定义域 URL 由配置自定义域名时唯一生成，并指定为 CloudFormation 输出参数。下文是[记录示例](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-basic.html)：**路由策略**：简单路由**记录名称**：`demo.api-gateway-custom-domain-versioning.example.com`**别名**：是**记录类型**：指向 AWS 资源的 “A” 类型的 DNS 记录**值**：`d-xxxxxxxxxx.execute-api.xx-xxxx-x.amazonaws.com`**TTL（秒）**：300 | 应用程序开发人员、AWS 系统管理员、网络管理员 | 

### 部署 CloudFormation 堆栈并调用 API
<a name="deploy-cfnshort-stacks-and-invoke-the-api"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 部署 `ApiStackV1` 堆栈。 | 要部署 `ApiStackV1` 堆栈，请使用以下命令：<pre>npm run deploy-v1</pre>以下 CDK 代码添加了 API 映射：<pre>var apiMapping = new CfnApiMapping(this, "ApiMapping", {<br />      apiId: this.lambdaRestApi.restApiId,<br />      domainName: props.customDomainName.domainName,<br />      stage: "api",<br />      apiMappingKey: "api/v1",<br />    });</pre> | 应用程序开发人员 | 
| 部署 `ApiStackV2` 堆栈。 | 要部署 `ApiStackV2` 堆栈，请使用以下命令：<pre>npm run deploy-v2</pre> | 应用程序开发人员 | 
| 调用 API。 | 要使用 Bruno 调用 API 并测试 API 端点，请参阅[其他信息](#implement-path-based-api-versioning-by-using-custom-domains-additional)中的说明。 | 应用程序开发人员 | 

### 清理 资源
<a name="clean-up-resources"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 清理资源。 | 要销毁与此示例应用程序关联的资源，请使用以下命令：<pre>npx cdk destroy --all</pre>请确认已清理为域所有权验证过程手动添加的所有 Route 53 DNS 记录。 | 应用程序开发人员 | 

## 问题排查
<a name="implement-path-based-api-versioning-by-using-custom-domains-troubleshooting"></a>


| 问题 | 解决方案 | 
| --- | --- | 
| `CustomDomainRouterStack` 部署超时，因为无法验证证书。 | 确认已按照之前的任务所述添加了正确的 DNS 验证 CNAME 记录。在添加 DNS 验证记录后，您的新证书可能会继续显示**等待验证**状态，最多 30 分钟。有关更多信息，请参阅 AWS Certificate Manager 文档中的 [DNS 验证](https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html)。 | 

## 相关资源
<a name="implement-path-based-api-versioning-by-using-custom-domains-resources"></a>
+ [使用 Amazon 实现基于标头的 API Gateway 版本控制 CloudFront](https://aws.amazon.com/blogs/compute/implementing-header-based-api-gateway-versioning-with-amazon-cloudfront/) — 这篇 AWS Compute 博客文章提供了一种基于标头的版本控制策略，作为该模式中概述的基于路径的版本控制策略的替代方案。
+ [AWS CDK 研讨会](https://cdkworkshop.com/20-typescript.html) — 此入门研讨会重点介绍如何使用构建和部署应用程序 AWS Cloud Development Kit (AWS CDK)。 AWS 本研讨会支持 Go、Python 和 TypeScript。

## 附加信息
<a name="implement-path-based-api-versioning-by-using-custom-domains-additional"></a>

**使用 Bruno 测试 API**

我们建议您使用开源 API 测试工具 [Bruno](https://www.usebruno.com/) 来验证基于路径的路由在该示例应用程序中是否正常运行。此模式提供了一个示例集合，有利于测试您的示例 API。

要调用和测试 API，请使用以下步骤：

1. [安装 Bruno。](https://www.usebruno.com/downloads)

1. 打开 Bruno。

1. 在此模式的[代码存储库](https://github.com/aws-samples/path-based-versioning-with-api-gateway)中，选择 **Bruno/Sample-API-Gateway-Custom-Domain-Versioning ** 并打开该集合。

1. 要查看用户界面（UI）右上角的**环境**下拉列表，请选择集合中的任何请求。

1. 在**环境**下拉列表中，选择**配置**。

1. 将 `REPLACE_ME_WITH_YOUR_DOMAIN` 值替换为您的自定义域。

1. 选择**保存**，然后关闭**配置**部分。

1. 对于**沙盒环境**，****请确认已选择**活跃**选项。

1. 针对所选请求，使用 **->** 按钮，以调用您的 API。

1. 请注意 V1 和 V2 中验证（传入非数字值）的处理方式有何不同之处。

要查看示例 API 调用的屏幕截图以及 V1 和 V2 验证的比较，请参阅在此模式的[代码存储库](https://github.com/aws-samples/path-based-versioning-with-api-gateway)中的 `README.md` 文件中的**测试示例 API**。