

# 工作负载架构
<a name="workload-architecture"></a>

 可靠的工作负载始于前期的软件和基础设施设计决策。您的架构选择会影响六个 Well-Architected 支柱的工作负载行为。针对可靠性，您必须遵循特定的模式。

 以下各节旨在介绍使用这些保证可靠性的模式时要遵循的最佳实践。

**Topics**
+ [设计工作负载服务架构](design-your-workload-service-architecture.md)
+ [在分布式系统中设计交互来预防发生故障](design-interactions-in-a-distributed-system-to-prevent-failures.md)
+ [在分布式系统中设计交互以减少或承受故障](design-interactions-in-a-distributed-system-to-mitigate-or-withstand-failures.md)

# 设计工作负载服务架构
<a name="design-your-workload-service-architecture"></a>

 使用服务导向型架构（SOA）或微服务架构构建高度可扩展的可靠工作负载。服务导向型架构（SOA）可通过服务接口使软件组件可重复使用。微服务架构则进一步让组件变得更小、更简单。

 服务导向型架构（SOA）接口采用常见的通信标准，以便快速地合成到新的工作负载。SOA 取代了构建整体架构的做法，后者由相互依赖、不可分割的单元组成。

 在 AWS，我们一直采用 SOA，但现在，我们会使用微服务构建我们的系统。虽然微服务有许多具有吸引力的特性，但就可用性而言，最重要的好处在于规模更小、更简单。它们可让您区分不同服务要求的可用性，从而更明确地专注于投资具有最大可用性需求的微服务。例如，要在 Amazon.com 上提供产品信息页面（“详情页面”），需要调用数百个微服务来构建页面的不同部分。虽然一定有一些服务可用于提供价格和产品详情，但如果服务不可用，页面上的绝大多数内容都可以直接排除在外。甚至不需要提供照片和评论等内容，客户也可以购买产品。

**Topics**
+ [REL03-BP01 选择如何划分工作负载](rel_service_architecture_monolith_soa_microservice.md)
+ [REL03-BP02 构建专注于特定业务领域和功能的服务](rel_service_architecture_business_domains.md)
+ [REL03-BP03 根据 API 提供服务合同](rel_service_architecture_api_contracts.md)

# REL03-BP01 选择如何划分工作负载
<a name="rel_service_architecture_monolith_soa_microservice"></a>

 在确定应用程序的弹性要求时，工作负载划分很重要。应尽量避免使用整体架构，仔细考虑哪些应用程序组件可以分解为多项微服务。应用程序具体需求各异，架构到最后往往会将服务导向型架构（SOA）与微服务架构两者结合起来。能够实现无状态的工作负载更容易部署为微服务。

 **期望结果：**工作负载应该可支持、可扩展，并且尽量做到松耦合。

 在选择如何划分工作负载时，要权衡其优点和复杂性。适用于即将首次发布的新产品的功能，有别于从一开始就构建用于扩展的工作负载的需求。重构一个现有的整体架构时，您需要考虑应用程序对无状态分解的支持程度。通过将服务分解为较小的部分，可以让职责明确的小型团队来开发和管理它们。然而，较小的服务会带来复杂性，包括可能会增加延迟，调试变得更复杂，而且加重运营负担。

 **常见反模式：**
+  [微服务 *Death Star*](https://mrtortoise.github.io/architecture/lean/design/patterns/ddd/2018/03/18/deathstar-architecture.html) 是这样一种情况：原子组件变得高度相互依赖，牵一发而动全身，使组件像一块整体一样死板而又脆弱。

 **建立此最佳实践的好处：**
+  更多特定分段可以提高敏捷性、组织灵活性和可扩展性。
+  减小了服务中断的影响。
+  应用程序组件可能有不同的可用性要求，可通过更加原子化的分段来满足这些要求。
+  支持工作负载的团队职责分明。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 请根据工作负载的分段方式选择架构类型。选择 SOA 或微服务架构（极少数情况下是整体架构）。即便在刚开始选择整体架构，您必须确保它是模块化的，而且由于您的产品随着采用的用户增加而扩展，它最终也可转变成为 SOA 或微服务架构。SOA 和微服务各自提供较小的区段，它们是现代可扩展和可靠架构的首选，但您需要认真权衡利弊，尤其在部署微服务架构时。

 一项主要的权衡是您现在使用的是分布式计算架构，可能更难实现用户延迟要求，还增加了调试和跟踪用户交互的复杂性。您可以使用 AWS X-Ray 来帮助解决此问题。需要考虑的另一个影响是，您管理的应用程序数量增加时，运营复杂性也会随之增加，这要求部署多个相互独立组件。

![\[图中显示了整体架构、服务导向型架构和微服务架构之间的比较\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/reliability-pillar/images/monolith-soa-microservices-comparison.png)


## 实施步骤
<a name="implementation-steps"></a>
+  确定构建或重构应用程序所需的适当架构。SOA 和微服务分别提供较小分段，这是现代可扩展的可靠架构的首选。要在实现较小分段的同时避免一些微服务复杂性，SOA 是很好的折中方案。有关更多详细信息，请参阅 [Microservice Trade-Offs](https://martinfowler.com/articles/microservice-trade-offs.html)。
+  如果工作负载适合，并且组织可以支持，则应使用微服务架构来实现最佳敏捷性和可靠性。有关更多详细信息，请参阅[在 AWS 上实施微服务](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/introduction.html)。
+  考虑按照 [*Strangler Fig* 模式](https://martinfowler.com/bliki/StranglerFigApplication.html)将整体重构为较小的组件。这包括使用新的应用程序和服务逐步替换特定的应用程序组件。[AWS Migration Hub Refactor Spaces](https://docs.aws.amazon.com/migrationhub-refactor-spaces/latest/userguide/what-is-mhub-refactor-spaces.html) 充当增量重构的起点。有关更多详细信息，请参阅 [Seamlessly migrate on-premises legacy workloads using a strangler pattern](https://aws.amazon.com/blogs/architecture/seamlessly-migrate-on-premises-legacy-workloads-using-a-strangler-pattern/)。
+  实施微服务可能需要服务发现机制，让这些分布式服务间能够相互通信。[AWS App Mesh](https://docs.aws.amazon.com/app-mesh/latest/userguide/what-is-app-mesh.html) 可用于服务导向型架构，提供对服务的可靠发现和访问。[AWS Cloud Map](https://aws.amazon.com/cloud-map/) 也可以用于基于 DNS 的动态服务发现。
+  如果要从整体架构迁移到 SOA，[Amazon MQ](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/welcome.html) 可以在重新设计云中的传统应用程序时作为服务总线帮助缩小差距。
+  对于具有单个共享数据库的现有整体架构，请选择将数据重组为较小分段的方式。可以按业务部门、访问模式或数据结构来划分。在重构过程的这一阶段，应选择是使用关系型还是非关系型（NoSQL）数据库来继续操作。有关更多详细信息，请参阅[从 SQL 到 NoSQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SQLtoNoSQL.html)。

 **实施计划的工作量级别：**高 

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL03-BP02 构建专注于特定业务领域和功能的服务](rel_service_architecture_business_domains.md) 

 **相关文档：**
+  [Amazon API Gateway：使用 OpenAPI 配置 REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html) 
+  [什么是服务导向型架构？](https://aws.amazon.com/what-is/service-oriented-architecture/) 
+  [Bounded Context (a central pattern in Domain-Driven Design)](https://martinfowler.com/bliki/BoundedContext.html) 
+  [在 AWS 上实施微服务](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/introduction.html) 
+  [Microservice Trade-Offs](https://martinfowler.com/articles/microservice-trade-offs.html) 
+  [Microservices - a definition of this new architectural term](https://www.martinfowler.com/articles/microservices.html) 
+  [AWS 上的微服务](https://aws.amazon.com/microservices/) 
+  [什么是 AWS App Mesh ？](https://docs.aws.amazon.com/app-mesh/latest/userguide/what-is-app-mesh.html) 

 **相关示例：**
+  [Iterative App Modernization 讲习会](https://catalog.us-east-1.prod.workshops.aws/workshops/f2c0706c-7192-495f-853c-fd3341db265a/en-US/intro) 

 **相关视频：**
+  [Delivering Excellence with Microservices on AWS](https://www.youtube.com/watch?v=otADkIyugzY) 

# REL03-BP02 构建专注于特定业务领域和功能的服务
<a name="rel_service_architecture_business_domains"></a>

服务导向型架构（SOA）采用按业务需求定义的、划分明确的功能来定义服务。微服务使用域模型和限界上下文，沿业务环境边界划定服务边界。通过将重点放在业务领域和功能上，有助于团队为其服务定义独立的可靠性要求。限界上下文隔离和封装业务逻辑，让团队能够更好地解释如何处理故障。

 **期望结果：**工程师和业务利益相关方共同定义限界上下文，并使用它们将系统设计为实现特定业务功能的服务。这些团队使用事件风暴等既定的实践来定义需求。新的应用程序被设计为服务，具有明确定义的边界并采用松耦合。现有整体式架构被分解为[限界上下文](https://martinfowler.com/bliki/BoundedContext.html)，而系统设计则朝着服务导向型架构或微服务架构转变。重构整体式架构时，会应用气泡上下文和整体式架构分解模式等既定方法。

 面向领域的服务作为一个或多个进程执行，彼此之间不分享状态。这些进程独立应对需求的波动，并根据特定领域的要求处理故障情景。

 **常见反模式：**
+  围绕特定技术领域（例如 UI 和 UX、中间件或数据库）组建团队，而不是根据特定的业务领域组建。
+  应用程序进行了领域职责划分。跨越限界上下文的服务可能更难于维护，需要更多测试工作，并且需要多个领域团队参与软件更新。
+  领域依赖关系（例如领域实体库）在服务之间共享，因此对一个服务领域进行更改也需要更改其他服务领域 
+  服务合同和业务逻辑没有使用通用且一致的领域语言来描述实体，这会导致翻译层的存在，使得系统更加复杂并增加调试工作量。

 **建立此最佳实践的好处：**应用程序被设计为独立的服务，按照业务领域确定界限，并使用通用的业务语言。服务可独立测试和部署。对于所实施的领域，服务满足领域特定的韧性要求。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 领域驱动型设计（DDD）是围绕业务领域设计和构建软件的基本方法。围绕业务领域构建服务时，使用现有框架会很有帮助。在使用现有的整体式应用程序时，您可以利用分解模式提供成熟的技术，将应用程序改造为现代化服务。

![\[描述领域驱动型设计方法的流程图。\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/reliability-pillar/images/domain-driven-decision.png)


 

## 实施步骤
<a name="implementation-steps"></a>
+  团队可以举办[事件风暴](https://serverlessland.com/event-driven-architecture/visuals/event-storming)讲习会，以简便的便签格式，快速确定事件、命令、聚合和领域。
+  在领域上下文中形成领域实体和功能后，您可以使用[限界上下文](https://martinfowler.com/bliki/BoundedContext.html)将领域划分为服务，将具有相似特征和属性的实体分成一组。通过将模型细分为不同的上下文，即可得到如何确定微服务边界的模板。
  +  以 Amazon.com 网站为例，实体可能包括包装、配送、时间表、价格、折扣和货币。
  +  包装、配送和时间表分组到运输上下文中，而价格、折扣和货币分组到定价上下文中。
+  [Decomposing monoliths into microservices](https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/welcome.html) 概述了重构微服务的模式。使用按照业务功能、子领域或事务进行分解的模式，与领域驱动型方法非常吻合。
+  利用[气泡上下文](https://www.domainlanguage.com/wp-content/uploads/2016/04/GettingStartedWithDDDWhenSurroundedByLegacySystemsV1.pdf)等战术性技巧，您可以在现有或旧版应用程序中引入 DDD，无需预先重新编写和承诺完全转向 DDD。在气泡上下文方法中，使用服务映射和协调来建立小型限界上下文，或建立[防损层](https://serverlessland.com/event-driven-architecture/visuals/messages-between-bounded-context)来保护新定义的领域模型免受外部影响。

 在团队进行了领域分析并定义实体和服务合同后，他们可以利用 AWS 服务，将自己的领域驱动型设计作为云端服务来实施。
+  通过定义执行领域业务规则的测试来开始开发。测试驱动型开发（TDD）和行为驱动型开发（BDD），有助于团队将服务重点放在解决业务问题上。
+  选择最符合业务领域要求和[微服务架构](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/microservices-on-aws.html)的 [AWS 服务](https://aws.amazon.com/microservices/)：
  +  [AWS 上的无服务器](https://aws.amazon.com/serverless/)服务让团队可以将精力集中于具体的领域逻辑上，而不是管理服务器和基础设施。
  +  [AWS 上的容器](https://aws.amazon.com/containers/)可简化基础设施的管理，让您可以将精力集中于领域要求上。
  +  [专用数据库](https://aws.amazon.com/products/databases/)有助于将领域要求与最适合的数据库类型相匹配。
+  [Building hexagonal architectures on AWS](https://docs.aws.amazon.com/prescriptive-guidance/latest/hexagonal-architectures/welcome.html) 中概述了一个框架，即从业务领域出发，采用逆向工作方法，将业务逻辑构建到服务中来满足功能要求，然后连接集成适配器。采用将接口详细信息从业务逻辑与 AWS 服务之间分离的模式，让团队能够专注于研究领域功能并提高软件质量。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL03-BP01 选择如何划分工作负载](rel_service_architecture_monolith_soa_microservice.md) 
+  [REL03-BP03 根据 API 提供服务合同](rel_service_architecture_api_contracts.md) 

 **相关文档：**
+ [AWS 微服务](https://aws.amazon.com/microservices/)
+  [在 AWS 上实施微服务](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/introduction.html) 
+  [How to break a Monolith into Microservices](https://martinfowler.com/articles/break-monolith-into-microservices.html) 
+  [Getting Started with DDD when Surrounded by Legacy Systems](https://domainlanguage.com/wp-content/uploads/2016/04/GettingStartedWithDDDWhenSurroundedByLegacySystemsV1.pdf) 
+ [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://www.amazon.com/gp/product/0321125215)
+ [Building hexagonal architectures on AWS](https://docs.aws.amazon.com/prescriptive-guidance/latest/hexagonal-architectures/welcome.html)
+ [Decomposing monoliths into microservices](https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/welcome.html)
+ [Event Storming](https://serverlessland.com/event-driven-architecture/visuals/event-storming)
+ [Messages Between Bounded Contexts](https://serverlessland.com/event-driven-architecture/visuals/messages-between-bounded-context)
+ [Microservices](https://www.martinfowler.com/articles/microservices.html)
+ [Test-driven development](https://en.wikipedia.org/wiki/Test-driven_development)
+ [Behavior-driven development](https://en.wikipedia.org/wiki/Behavior-driven_development)

 **相关示例：**
+ [Designing Cloud Native Microservices on AWS (from DDD/EventStormingWorkshop)](https://github.com/aws-samples/designing-cloud-native-microservices-on-aws/tree/main)

 **相关工具：**
+ [AWS 云 数据库](https://aws.amazon.com/products/databases/)
+ [AWS 上的无服务器](https://aws.amazon.com/serverless/)
+ [AWS 上的容器](https://aws.amazon.com/containers/)

# REL03-BP03 根据 API 提供服务合同
<a name="rel_service_architecture_api_contracts"></a>

服务合同是 API 生产者与使用者之间的书面协议，采用机器可读的 API 定义形式进行定义。合同版本控制策略让使用者能够继续使用现有的 API，并在更新的 API 准备就绪时，将其应用程序迁移到更新的 API。只要遵守合同，生产者部署可随时进行。服务团队可以使用自己选择的技术堆栈来满足 API 合同要求。

 **期望结果：**使用服务导向型架构或微服务架构所构建的应用程序能够独立运行，但具有集成的运行时系统依赖项。当双方都遵循共同的 API 合同时，向 API 使用者或生产者部署更改并不会影响整个系统的稳定性。通过服务 API 进行通信的组件能够独立执行功能发布、升级到运行时系统依赖项或者失效转移到灾难恢复（DR）站点，而彼此之间的影响很小，或者根本没有影响。此外，离散服务能够独立扩展来满足资源需求，无需统一扩展其他服务。

 **常见反模式：**
+  创建不使用强类型架构的服务 API。这样，API 不能用来生成无法通过编程方式验证的 API 绑定和有效负载。
+  不采用版本控制策略，会迫使 API 使用者在服务合同变化时进行更新和发布，否则会出现故障。
+  错误消息会泄露基础服务的实施细节，而不是按照域上下文和语言描述集成故障。
+  不使用 API 合同开发测试用例和模拟 API 实施，以便对服务组件进行独立测试。

 **建立此最佳实践的好处：**分布式系统由通过 API 服务合同进行通信的组件组成，可以提高可靠性。开发人员可以在开发过程的早期发现潜在问题，在编译期间进行类型检查，来验证请求和响应是否符合 API 合同以及是否存在必填字段。API 合同为 API 提供了清晰的自描述接口，并在不同的系统和编程语言之间提供了更好的互操作性。

 **在未建立这种最佳实践的情况下暴露的风险等级：**中 

## 实施指导
<a name="implementation-guidance"></a>

 确定业务领域并确定工作负载划分后，即可开发服务 API。首先，为 API 定义机器可读的服务合同，然后实施 API 版本控制策略。在准备好通过 REST、GraphQL 等常见协议或异步事件来集成服务时，您可以将 AWS 服务整合到架构中，从而将组件与强类型的 API 合同集成。

 **面向服务 API 合同的 AWS 服务** 

 将包括 [Amazon API Gateway](https://aws.amazon.com/api-gateway/)、[AWS AppSync](https://aws.amazon.com/appsync/) 和 [Amazon EventBridge](https://aws.amazon.com/eventbridge/) 在内的 AWS 服务整合到架构中，以便在应用程序中使用 API 服务合同。Amazon API Gateway 有助于直接与原生 AWS 服务和其他网络服务集成。API Gateway 支持 [OpenAPI 规范](https://github.com/OAI/OpenAPI-Specification)和版本控制。AWS AppSync 属于 [GraphQL](https://graphql.org/) 托管端点，您可以通过定义 GraphQL 架构来配置该端点，定义用于查询、突变和订阅的服务接口。Amazon EventBridge 使用事件架构来定义事件，为事件生成代码绑定。

## 实施步骤
<a name="implementation-steps"></a>
+  首先，为您的 API 定义一个合同。合同将说明 API 的功能，并为 API 的输入和输出定义强类型的数据对象和字段。
+  在 API Gateway 中配置 API 时，您可以导入和导出端点的 OpenAPI 规范。
  +  [导入 OpenAPI 定义](https://docs.aws.amazon.com/apigateway/latest/developerguide/import-edge-optimized-api.html)可简化 API 的创建过程，并可与 AWS 基础设施即代码工具（例如 [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) 和 [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk/)）集成。
  +  [导出 API 定义](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-export-api.html)可简化与 API 测试工具的集成，并为服务使用者提供集成规范。
+  您可以通过[定义 GraphQL 架构](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)文件，使用 AWS AppSync 来定义和管理 GraphQL API，从而生成合同接口，并简化与复杂 REST 模型、多个数据库表或传统服务的交互。
+  [AWS Amplify](https://aws.amazon.com/amplify/) 项目与 AWS AppSync 集成后，会生成强类型的 JavaScript 查询文件供应用程序使用，还会生成 AWS AppSync GraphQL 客户端库供 [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) 表使用。
+  当您使用来自 Amazon EventBridge 的服务事件时，事件遵循架构注册表中已有的架构或您使用 OpenAPI 规范定义的架构。通过在注册表中定义架构，您还可以从架构合同生成客户端绑定，以将代码与事件集成。
+  扩展 API 或者实施 API 版本控制。在添加可以配置为可选字段的字段时，或者为必填字段添加默认值时，扩展 API 是一种相对比较简单的选项。
  +  对于 REST 和 GraphQL 等协议，基于 JSON 的合同可能非常适合合同扩展。
  +  对于 SOAP 等协议，基于 XML 的合同应与服务使用者一起进行测试，来确定合同扩展的可行性。
+  对 API 进行版本控制时，可以考虑实施代理版本控制，其中使用 Facade 模式来支持版本，这样就能够在单个代码库中维护逻辑。
  +  借助 API Gateway，您可以使用[请求和响应映射](https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html#transforming-request-response-body)，通过建立 Facade 模式为新字段提供默认值，或者从请求或响应中除去已删除的字段，从而简化接受合同变更的过程。通过这种方法，底层服务可以维护单个代码库。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL03-BP01 选择如何划分工作负载](rel_service_architecture_monolith_soa_microservice.md) 
+  [REL03-BP02 构建专注于特定业务领域和功能的服务](rel_service_architecture_business_domains.md) 
+  [REL04-BP02 实施松耦合的依赖关系](rel_prevent_interaction_failure_loosely_coupled_system.md) 
+  [REL05-BP03 控制与限制重试调用](rel_mitigate_interaction_failure_limit_retries.md) 
+  [REL05-BP05 设置客户端超时](rel_mitigate_interaction_failure_client_timeouts.md) 

 **相关文档：**
+ [什么是 API（应用程序编程接口）？](https://aws.amazon.com/what-is/api/)
+ [在 AWS 上实施微服务](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/microservices-on-aws.html)
+ [Microservice Trade-Offs](https://martinfowler.com/articles/microservice-trade-offs.html)
+ [Microservices – a definition of this new architectural term](https://www.martinfowler.com/articles/microservices.html)
+ [AWS 上的微服务](https://aws.amazon.com/microservices/)
+ [使用基于 OpenAPI 的 API Gateway 扩展](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html)
+ [OpenAPI-Specification](https://github.com/OAI/OpenAPI-Specification)
+ [GraphQL: Schemas and Types](https://graphql.org/learn/schema/)
+ [Amazon EventBridge code bindings](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-schema-code-bindings.html)

 **相关示例：**
+ [Amazon API Gateway：使用 OpenAPI 配置 REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html)
+ [Amazon API Gateway to Amazon DynamoDB CRUD application using OpenAPI](https://serverlessland.com/patterns/apigw-ddb-openapi-crud?ref=search)
+ [Modern application integration patterns in a serverless age: API Gateway Service Integration](https://catalog.us-east-1.prod.workshops.aws/workshops/be7e1ee7-b91f-493d-93b0-8f7c5b002479/en-US/labs/asynchronous-request-response-poll/api-gateway-service-integration)
+ [Implementing header-based API Gateway versioning with Amazon CloudFront](https://aws.amazon.com/blogs/compute/implementing-header-based-api-gateway-versioning-with-amazon-cloudfront/)
+ [AWS AppSync: Building a client application](https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app.html#aws-appsync-building-a-client-app)

 **相关视频：**
+ [Using OpenAPI in AWS SAM to manage API Gateway](https://www.youtube.com/watch?v=fet3bh0QA80)

 **相关工具：**
+ [Amazon API Gateway](https://aws.amazon.com/api-gateway/)
+ [AWS AppSync](https://aws.amazon.com/appsync/)
+ [Amazon EventBridge](https://aws.amazon.com/eventbridge/)

# 在分布式系统中设计交互来预防发生故障
<a name="design-interactions-in-a-distributed-system-to-prevent-failures"></a>

 分布式系统依靠通信网络来互连组件，例如服务器或服务。即使这些网络中出现数据丢失或延迟情况，您的工作负载也必须可靠运行。分布式系统组件的运行方式不得对其他组件或工作负载产生负面影响。这些最佳实践可以防止故障并缩短平均故障间隔时间 (MTBF)。

**Topics**
+ [REL04-BP01 确定所依赖的分布式系统的类型](rel_prevent_interaction_failure_identify.md)
+ [REL04-BP02 实施松耦合的依赖关系](rel_prevent_interaction_failure_loosely_coupled_system.md)
+ [REL04-BP03 持续工作](rel_prevent_interaction_failure_constant_work.md)
+ [REL04-BP04 使变异操作幂等](rel_prevent_interaction_failure_idempotent.md)

# REL04-BP01 确定所依赖的分布式系统的类型
<a name="rel_prevent_interaction_failure_identify"></a>

 分布式系统可以是同步系统、异步系统或批处理系统。同步系统必须尽可能快地处理请求，并使用 HTTP/S、REST 或远程过程调用（RPC，Remote Procedure Call）协议，同步地发出请求和响应调用，来彼此通信。异步系统在彼此通信时通过中间服务来异步交换数据，无需将各个系统耦合在一起。批处理系统则会接收大量输入数据，无需人工干预即可运行自动数据处理，并生成输出数据。

 **期望结果**：设计能够与同步、异步和批处理依赖项进行有效交互的工作负载。

 **常见反模式：**
+  工作负载无限期地等待其依赖项的响应，这可能导致工作负载客户端超时，不知道其请求是否已被接收。
+  工作负载使用会同步调用彼此的依赖系统链。这种模式要求每个系统都可用并能成功处理请求，整个链才能成功运行，这导致很容易出现崩溃行为，影响到整体可用性。
+  工作负载与其依赖项异步通信，并依赖于保证消息传递且仅传递一次的概念，但仍然会经常收到重复的消息。
+  工作负载没有使用正确的批处理调度工具，导致允许并行执行相同的批处理作业。

 **建立此最佳实践的好处：**对于给定的工作负载，通常能够在同步、异步和批处理之间实施一种或多种通信方式。此最佳实践可帮助您确定，选择每种通信方式所面对的不同权衡，以便让您的工作负载能够承受其任意依赖项中断所带来的干扰。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 以下各节针对每种依赖项，介绍了一般性实施指导和具体实施指导。

 **一般指导** 
+  确保您的依赖项提供的性能和可靠性服务级别目标（SLO，Service-Level Objective），能够满足工作负载的性能和可靠性要求。
+  使用 [AWS 可观测性服务](https://aws.amazon.com/cloudops/monitoring-and-observability)来[监控响应时间和错误率](https://www.youtube.com/watch?v=or7uFFyHIX0)，确保依赖项提供的服务达到工作负载所需的水平。
+  确定您的工作负载在与其依赖项进行通信时，可能会遇到的潜在挑战。分布式系统[面临着诸多挑战](https://aws.amazon.com/builders-library/challenges-with-distributed-systems/)，可能会增加架构的复杂性、运营负担和成本。常见的挑战包括延迟、网络中断、数据丢失、可扩展性和数据复制延迟。
+  实施强大的错误处理和[日志记录](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)，在依赖项遇到问题时帮助排查问题。

 **同步依赖项** 

 在同步通信中，工作负载会向其依赖项发送请求并停止操作来等待响应。当其依赖项收到请求时，依赖项会尝试尽快处理请求并将响应发送回工作负载。同步通信面临的一个巨大挑战是它会导致时间耦合，这要求您的工作负载及其依赖项同时可用。当您的工作负载需要与其依赖项以同步方式通信时，请考虑以下指南：
+  工作负载在执行单个功能时，不应依赖多个同步依赖项。这种依赖项链会导致整体更加脆弱，因为要想完成请求，路径中的所有依赖项都必须可用。
+  请确定当依赖项运行状况不佳或不可用时，您采用的错误处理和重试策略。避免使用双模态行为。双模态行为是指工作负载在正常模式和故障模式下表现出不同的行为。有关双模态行为的更多详细信息，请参阅 [REL11-BP05 使用静态稳定性来防止双模态行为](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_withstand_component_failures_static_stability.html)。
+  请记住，快速失效机制比让工作负载等待要好。例如，《[AWS Lambda 开发人员指南](https://docs.aws.amazon.com/lambda/latest/dg/invocation-retries.html)》描述了在调用 Lambda 函数时如何处理重试和失败。
+  设置工作负载调用其依赖项时的超时。这种技术可以避免等待太长时间或无限期等待响应。有关此主题的实用讨论，请参阅 [Tuning AWS Java SDK HTTP request settings for latency-aware Amazon DynamoDB applications](https://aws.amazon.com/blogs/database/tuning-aws-java-sdk-http-request-settings-for-latency-aware-amazon-dynamodb-applications/)。
+  在完成单个请求时，尽可能减少从工作负载对依赖项进行的调用次数。在它们之间进行的频繁调用会增加耦合和延迟。

 **异步依赖项** 

 要想临时将工作负载与其依赖项解耦，就应该采取异步通信。使用异步方法，您的工作负载无需等待其依赖项或依赖项链发送响应，即可继续进行任何其他处理。

 当您的工作负载需要与其依赖项以异步方式通信时，请考虑以下指南：
+  根据应用场景和要求，确定是使用消息收发还是事件流。[消息收发](https://aws.amazon.com/messaging/)可让工作负载通过消息代理发送和接收消息，从而与其依赖项进行通信。[事件流](https://aws.amazon.com/streaming-data/)可让工作负载及其依赖项利用流服务来发布和订阅以连续数据流形式交付且需尽快处理的事件。
+  消息收发和事件流以不同的方法来处理消息，因此您需要根据以下因素作出权衡决策：
  +  **消息优先级：**消息代理可以先处理高优先级消息，再处理普通消息。在事件流中，所有消息具有相同的优先级。
  +  **消息使用**：消息代理确保使用者能够收到消息。事件流使用器必须跟踪所读取的每一条消息。
  +  **消息排序**：除非对消息收发使用先进先出（FIFO）方法，否则无法保证按照发送消息的确切顺序接收消息。事件流则始终保留数据生成的顺序。
  +  **消息删除**：使用消息收发时，使用者必须在处理消息后将其删除。事件流服务则将消息附加到流并一直保留在流中，直到消息的保留期到期。这种删除策略让事件流非常适合重放消息。
+  定义如何让工作负载在其依赖项完成工作时了解这一信息。例如，当工作负载[异步调用 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html)时，Lambda 将请求置于队列中并返回成功响应，而不返回其他信息。处理完成后，Lambda 函数可以[将结果发送到目标](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations)，该目标可根据成功或失败进行配置。
+  利用幂等性，构建工作负载以处理重复的消息。幂等性意味着，即使您的工作负载针对同一消息多次生成结果，这些结果也会保持不变。需要指出的是，如果发生网络故障或未收到确认，则[消息收发](https://aws.amazon.com/sqs/faqs/#FIFO_queues)或[流](https://docs.aws.amazon.com/streams/latest/dev/kinesis-record-processor-duplicates.html)服务将重新发送消息。
+  如果您的工作负载没有从其依赖项获得响应，则需要重新提交请求。请考虑限制重试次数，以保留工作负载的 CPU、内存和网络资源用于处理其他请求。[AWS Lambda 文档](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-errors)介绍了如何处理异步调用错误。
+  利用合适的可观测性、调试和跟踪工具，来管理和操作工作负载与其依赖项的异步通信。您可以使用 [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) 来监控[消息收发](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-available-cloudwatch-metrics.html)和[事件流](https://docs.aws.amazon.com/streams/latest/dev/monitoring-with-cloudwatch.html)服务。您还可以使用 [AWS X-Ray](https://aws.amazon.com/xray/) 检测工作负载，快速[获得洞察](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html)来排查问题。

 **批处理依赖项** 

 批处理系统获取输入数据，启动一系列作业来处理数据，然后生成一些输出数据，整个过程无需人工干预。根据数据大小，作业的运行时间可能只需要几分钟，而在某些情况下，也可能长达数天。当您的工作负载与其批处理依赖项通信时，请考虑以下指南：
+  定义工作负载应运行批处理作业的时间窗口。工作负载可以设置重复模式来调用批处理系统，例如每小时或每月月底。
+  确定数据输入的位置，以及处理后数据输出的位置。选择一种能让工作负载大规模读取和写入文件的存储服务，例如 [Amazon Simple Storage Service（Amazon S3）](https://aws.amazon.com/s3/)、[Amazon Elastic File System（Amazon EFS）](https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html)和[适用于 Lustre 的 Amazon FSx](https://docs.aws.amazon.com/fsx/latest/LustreGuide/what-is.html)。
+  如果工作负载需要调用多个批处理作业，则可以利用 [AWS Step Functions](https://aws.amazon.com/step-functions/?step-functions.sort-by=item.additionalFields.postDateTime&step-functions.sort-order=desc) 来简化在 AWS 内部或本地运行的批处理作业的编排。此[示例项目](https://github.com/aws-samples/aws-stepfunction-complex-orchestrator-app)演示了使用 Step Functions、[AWS Batch](https://aws.amazon.com/batch/) 和 Lambda 编排批处理作业。
+  监控批处理作业以发现异常情况，例如作业完成用时超过了应有的时间。您可以使用 [CloudWatch Container Insights](https://docs.aws.amazon.com/batch/latest/userguide/cloudwatch-container-insights.html) 之类的工具来监控 AWS Batch 环境和作业。在这种情况下，工作负载会从头停止下一个作业，并向相关人员通知异常情况。

## 资源
<a name="resources"></a>

 **相关文档：**
+  [AWS 云 运维：监控和可观测性](https://aws.amazon.com/cloudops/monitoring-and-observability) 
+  [Amazon Builders' Library：分布式系统相关挑战](https://aws.amazon.com/builders-library/challenges-with-distributed-systems/) 
+  [REL11-BP05 使用静态稳定性来防止双模态行为](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_withstand_component_failures_static_stability.html) 
+  [AWS Lambda 开发人员指南：AWS Lambda 中的错误处理和自动重试](https://docs.aws.amazon.com/lambda/latest/dg/invocation-retries.html) 
+  [Tuning AWS Java SDK HTTP request settings for latency-aware Amazon DynamoDB applications](https://aws.amazon.com/blogs/database/tuning-aws-java-sdk-http-request-settings-for-latency-aware-amazon-dynamodb-applications/) 
+  [AWS 消息收发](https://aws.amazon.com/messaging/) 
+  [什么是流数据？](https://aws.amazon.com/streaming-data/) 
+  [AWS Lambda 开发人员指南：异步调用](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html) 
+  [Amazon Simple Queue Service 常见问题：FIFO 队列](https://aws.amazon.com/sqs/faqs/#FIFO_queues) 
+  [Amazon Kinesis Data Streams Developer Guide: Handling Duplicate Records](https://docs.aws.amazon.com/streams/latest/dev/kinesis-record-processor-duplicates.html) 
+  [Amazon Simple Queue Service Developer Guide: Available CloudWatch metrics for Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-available-cloudwatch-metrics.html) 
+  [Amazon Kinesis Data Streams Developer Guide: Monitoring the Amazon Kinesis Data Streams Service with Amazon CloudWatch](https://docs.aws.amazon.com/streams/latest/dev/monitoring-with-cloudwatch.html) 
+  [AWS X-Ray Developer Guide: AWS X-Ray concepts](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html) 
+  [AWS Samples on GitHub: AWS Step functions Complex Orchestrator App](https://github.com/aws-samples/aws-stepfunction-complex-orchestrator-app) 
+  [AWS Batch User Guide: AWS Batch CloudWatch Container Insights](https://docs.aws.amazon.com/batch/latest/userguide/cloudwatch-container-insights.html) 

 **相关视频：**
+  [AWS Summit SF 2022 – Full-stack observability and application monitoring with AWS (COP310)](https://www.youtube.com/watch?v=or7uFFyHIX0) 

 **相关工具：**
+  [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) 
+  [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) 
+  [AWS X-Ray](https://aws.amazon.com/xray/) 
+  [Amazon Simple Storage Service（Amazon S3）](https://aws.amazon.com/s3/) 
+  [Amazon Elastic File System (Amazon EFS)](https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html) 
+  [适用于 Lustre 的 Amazon FSx](https://docs.aws.amazon.com/fsx/latest/LustreGuide/what-is.html) 
+  [AWS Step Functions](https://aws.amazon.com/step-functions/?step-functions.sort-by=item.additionalFields.postDateTime&step-functions.sort-order=desc) 
+  [AWS Batch](https://aws.amazon.com/batch/) 

# REL04-BP02 实施松耦合的依赖关系
<a name="rel_prevent_interaction_failure_loosely_coupled_system"></a>

 队列系统、流系统、工作流和负载均衡器等依赖关系是松耦合的。松耦合有助于隔离某个组件的行为与依赖于它的其他组件的行为，从而提升韧性和敏捷性。

 解耦依赖关系（例如排队系统、流系统和工作流程），有助于最大限度地减少更改或故障对系统的影响。这种分离将组件的行为与依赖该组件的其他行为隔离开来，从而提高了韧性和敏捷性。

 在紧耦合的系统中，更改一个组件可能导致需要更改依赖该组件的其他组件，从而使所有组件的性能均降低。*松*耦合会打破这种依赖关系，使存在依赖关系的组件只需了解经过版本控制而且已发布的接口。在依赖项之间实施松耦合将隔离一个组件中的故障，防止对其他组件造成影响。

 松耦合允许您修改代码或向组件添加功能，同时最大限度地降低依赖于该组件的其他组件的风险。它还允许在组件级别实现精细的韧性，让您可以横向扩展或甚至改变依赖项的底层实施。

 要通过松耦合进一步提升韧性，在可能的情况下采用异步组件交互。若确定对请求进行注册已足够，则此模型适用于无需立即响应的任何交互。它包含一个生成事件的组件和另外一个使用事件的组件。两个组件不会通过直接点对点交互，但通常经由中间持久存储层集成，例如 Amazon SQS 队列或是 Amazon Kinesis 或 AWS Step Functions 这样的就流数据平台。

![\[图中显示了队列系统和负载均衡器等依赖关系是松散耦合的\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/reliability-pillar/images/dependency-diagram.png)


 Amazon SQS 队列和 AWS Step Functions 只是为松耦合增加中间层的两种方式。您还可以使用 Amazon EventBridge 在 AWS 云 中构建事件驱动型架构，而 Amazon EventBridge 可从其依赖的服务（事件使用器）中提取客户端（事件产生器）。如果需要进行高吞吐量、基于推送的多对多消息收发，Amazon Simple Notiﬁcation Service（Amazon SNS）是可供选择的高效解决方案。通过 Amazon SNS 主题，您的发布者系统可以将消息扇出到大量订阅用户端点以便进行并行处理。

 虽然队列具有多项优点，但在大多数硬性实时系统中，早于阈值时间（通常为秒）的请求应被视为过时（客户端已放弃而且不再等待响应）而不被处理。因此，较新（而且可能依然有效）的请求会被处理。

 **期望结果：**实施松耦合依赖项可以将故障的影响范围最大限度地缩小到组件级别，有助于诊断和解决问题。松耦合还简化了开发周期，允许团队在模块级别实施更改，而不会影响依赖它的其他组件的性能。这种方法能够根据资源需求以及有助于提高成本效益的组件利用率，在组件层面进行横向扩展。

 **常见反模式：**
+  部署整体工作负载。
+  直接在工作负载层之间调用 API，不具备失效转移或异步处理请求的功能。
+  使用共享数据进行紧密耦合。松耦合的系统应避免通过共享数据库或其他形式的紧密耦合数据存储共享数据，这可能会重新引入紧耦合并阻碍可扩展性。
+  忽略背压。当组件无法以相同速度处理传入数据时，您的工作负载应该能够减慢或停止传入数据。

 **建立此最佳实践的好处：**松耦合有助于隔离某个组件的行为与依赖于它的其他组件的行为，从而提升韧性和敏捷性。组件中的故障相互隔离。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 实施松耦合的依赖关系。可利用多种解决方案来构建松耦合的应用程序。其中包括用于实施全面托管的队列、自动化工作流、对事件的反应以及 API 等内容的服务，这些服务有助于将组件的行为相互隔离，从而提高韧性和敏捷性。
+  **构建事件驱动型架构：**[Amazon EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html) 有助于构建松耦合和分布式的事件驱动架构。
+  **在分布式系统中实施队列：**可以使用 [Amazon Simple Queue Service（Amazon SQS）](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html)集成或解耦分布式系统。
+  **将组件容器化为微服务：**[微服务](https://aws.amazon.com/microservices/)有助于团队构建由小型独立组件组成且通过明确定义的 API 进行通信的应用程序。[Amazon Elastic Container Service（Amazon ECS）](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html)和 [Amazon Elastic Kubernetes Service（Amazon EKS）](https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html)有助于快速使用容器。
+  **使用 Step Functions 管理工作流程：**[Step Functions ](https://aws.amazon.com/step-functions/getting-started/) 有助于将多个 AWS 服务协调为灵活的工作流程。
+  **利用发布-订阅（pub/sub）消息收发架构：**[Amazon Simple Notification Service（Amazon SNS）](https://docs.aws.amazon.com/sns/latest/dg/welcome.html)提供从发布者到订阅用户（也称为生产者和使用者）的消息传输。

### 实施步骤
<a name="implementation-steps"></a>
+  事件驱动型架构中的组件由事件启动。事件是系统中发生的操作，例如用户将商品添加到购物车。操作成功后，将生成一个激活系统的下一个组件的事件。
  + [Building Event-driven Applications with Amazon EventBridge](https://aws.amazon.com/blogs/compute/building-an-event-driven-application-with-amazon-eventbridge/)
  + [AWS re:Invent 2022 – Designing Event-Driven Integrations using Amazon EventBridge](https://www.youtube.com/watch?v=W3Rh70jG-LM)
+  分布式消息收发系统主要有三个部分，需要为基于队列的架构实施这些部分。它们包括分布式系统的组件、用于解耦的队列（分布在 Amazon SQS 服务器上）以及队列中的消息。典型的系统有将消息发送到队列中的产生器和从队列接收消息的使用器。该队列将消息存储在多台 Amazon SQS 服务器上以实现冗余。
  + [Basic Amazon SQS architecture](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html)
  + [使用 Amazon Simple Queue Service 在分布式应用程序间发送消息](https://aws.amazon.com/getting-started/hands-on/send-messages-distributed-applications/)
+  由于松耦合的组件由独立团队管理，因此微服务如果得到充分利用，可以增强可维护性并提高可扩展性。它还允许在发生变化时将行为隔离到单个组件。
  + [在 AWS 上实施微服务](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/microservices-on-aws.html)
  + [Let's Architect\$1 Architecting microservices with containers](https://aws.amazon.com/blogs/architecture/lets-architect-architecting-microservices-with-containers/)
+  借助 AWS Step Functions，您可以构建分布式应用程序、实现流程自动化、编排微服务等。将多个组件编排到一个自动化工作流程中，让您可以将应用程序中的依赖关系解耦。
  + [使用 AWS Step Functions 和 AWS Lambda 创建无服务器工作流程](https://aws.amazon.com/tutorials/create-a-serverless-workflow-step-functions-lambda/)
  + [AWS Step Functions 入门](https://aws.amazon.com/step-functions/getting-started/)

## 资源
<a name="resources"></a>

 **相关文档：**
+  [Amazon EC2: Ensuring Idempotency](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html) 
+  [Amazon Builders' Library：分布式系统相关挑战](https://aws.amazon.com/builders-library/challenges-with-distributed-systems/) 
+  [Amazon Builders' Library：Reliability, constant work, and a good cup of coffee](https://aws.amazon.com/builders-library/reliability-and-constant-work/) 
+  [什么是 Amazon EventBridge？](https://docs.aws.amazon.com/eventbridge/latest/userguide/what-is-amazon-eventbridge.html) 
+  [What Is Amazon Simple Queue Service?](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html)
+ [Break up with your monolith](https://pages.awscloud.com/break-up-your-monolith.html)
+ [Orchestrate Queue-based Microservices with AWS Step Functions and Amazon SQS](https://aws.amazon.com/tutorials/orchestrate-microservices-with-message-queues-on-step-functions/)
+ [Basic Amazon SQS architecture](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html)
+ [Queue-Based Architecture](https://docs.aws.amazon.com/wellarchitected/latest/high-performance-computing-lens/queue-based-architecture.html)

 **相关视频：**
+  [AWS New York Summit 2019: Intro to Event-driven Architectures and Amazon EventBridge (MAD205)](https://youtu.be/tvELVa9D9qU) 
+  [AWS re:Invent 2018: Close Loops and Opening Minds: How to Take Control of Systems, Big and Small ARC337 (includes loose coupling, constant work, static stability)](https://youtu.be/O8xLxNje30M) 
+  [AWS re:Invent 2019: Moving to event-driven architectures (SVS308)](https://youtu.be/h46IquqjF3E) 
+ [AWS re:Invent 2019: Scalable serverless event-driven applications using Amazon SQS and Lambda ](https://www.youtube.com/watch?v=2rikdPIFc_Q)
+ [AWS re:Invent 2022 – Designing Event-Driven Integrations using Amazon EventBridge](https://www.youtube.com/watch?v=W3Rh70jG-LM)
+ [AWS re:Invent 2017: Elastic Load Balancing Deep Dive and Best Practices ](https://www.youtube.com/watch?v=9TwkMMogojY)

# REL04-BP03 持续工作
<a name="rel_prevent_interaction_failure_constant_work"></a>

 系统会在负载中存在剧烈快速更改时失败。例如，如果您的工作负载执行的一项运行状况检查监控着数千个服务器的运行状况，每次都应发送相同大小的有效负载（当前状态的完整快照）。无论是否有服务器或有多少服务器发生故障，运行状况检查系统都会持续工作，而不会有剧烈、快速的变动。

 例如，如果运行状况检查系统正在监控 10 万台服务器，在通常较低的服务器故障率下，它的负载是正常的。但如果发生重大事件让一半的服务器运行状况不佳，则运行状况检查系统会因为尝试更新通知系统以及向其客户端传送状态而变得不堪重负。因此，运行状况检查系统每次都应发送当前状态的完整快照，10 万台服务器的运行状况状态（每个状态都用一位表示）仅占 12.5 KB 的有效负载。无论是没有服务器发生故障还是所有服务器都发生故障，运行状况检查系统都会持续工作，而大幅度骤变也不会威胁到系统的稳定性。这实际上就是 Amazon Route 53 处理对端点（例如 IP 地址）运行状况检查的方式，从而确定最终用户如何路由到这些端点。

 **在未建立这种最佳实践的情况下暴露的风险等级：**低 

## 实施指导
<a name="implementation-guidance"></a>
+  持续工作，这样系统就不会在负载发生骤变时出现故障。
+  实施松耦合的依赖关系。队列系统、流系统、工作流和负载均衡器等依赖关系是松耦合的。松耦合有助于隔离某个组件的行为与依赖于它的其他组件的行为，从而提升韧性和敏捷性。
  +  [Amazon Builders' Library：Reliability, constant work, and a good cup of coffee](https://aws.amazon.com/builders-library/reliability-and-constant-work/) 
  +  [AWS re:Invent 2018: Close Loops and Opening Minds: How to Take Control of Systems, Big and Small ARC337 (includes constant work)](https://youtu.be/O8xLxNje30M?t=2482) 
    +  以监控 10 万台服务器的运行状况检查系统为例，对工作负载进行设计，确保无论成功或失败次数如何，有效负载大小都保持不变。

## 资源
<a name="resources"></a>

 **相关文档：**
+  [Amazon EC2: Ensuring Idempotency](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html) 
+  [Amazon Builders' Library：分布式系统相关挑战](https://aws.amazon.com/builders-library/challenges-with-distributed-systems/) 
+  [Amazon Builders' Library：Reliability, constant work, and a good cup of coffee](https://aws.amazon.com/builders-library/reliability-and-constant-work/) 

 **相关视频：**
+  [AWS New York Summit 2019: Intro to Event-driven Architectures and Amazon EventBridge (MAD205)](https://youtu.be/tvELVa9D9qU) 
+  [AWS re:Invent 2018: Close Loops and Opening Minds: How to Take Control of Systems, Big and Small ARC337 (includes constant work)](https://youtu.be/O8xLxNje30M?t=2482) 
+  [AWS re:Invent 2018: Close Loops and Opening Minds: How to Take Control of Systems, Big and Small ARC337 (includes loose coupling, constant work, static stability)](https://youtu.be/O8xLxNje30M) 
+  [AWS re:Invent 2019: Moving to event-driven architectures (SVS308)](https://youtu.be/h46IquqjF3E) 

# REL04-BP04 使变异操作幂等
<a name="rel_prevent_interaction_failure_idempotent"></a>

 幂等服务承诺每个请求只确切处理一次，因此发起多个相同请求与发起单个请求的效果相同。这使客户端可以更轻松地进行重试，而不必担心多次错误地处理请求。要执行此操作，客户端可以发出具有幂等性令牌的 API 请求，每当重复该请求时都会使用此令牌。幂等服务 API 使用令牌来返回响应，该响应与首次完成请求时返回的响应相同，即使系统的底层状态已经改变也是如此。

 在分布式系统中，至多（客户端仅发起一个请求）或至少（持续发起请求直到客户端收到成功确认）执行某项操作一次相对简单。难就难在要保证某项操作*确切执行一次*，从而使发出多个相同的请求和发出单个请求具有一样的效果。在 API 中使用幂等性令牌，服务可以一次或多次收到变异请求，而不需要创建重复的记录或产生副作用。

 **期望结果：**您有一个一致、有据可查且广泛采用的方法来确保跨所有组件和服务的幂等性。

 **常见反模式：**
+  您不加选择地应用幂等性，即使不需要也是如此。
+  您引入过于复杂的逻辑来实现幂等性。
+  您使用时间戳作为幂等性的密钥。由于时钟偏差或多个客户端使用相同的时间戳来应用更改，这可能会导致不准确。
+  您存储整个有效载荷以保持幂等性。在这种方法中，您为每个请求保存完整的数据有效载荷，并对于每个新请求将其覆盖。这可能会降低性能并影响可扩展性。
+  您在不同服务之间以不一致的方式生成密钥。如果密钥不一致，服务可能无法识别重复的请求，从而导致意想不到的结果。

 **建立此最佳实践的好处：**
+  提高了可扩展性：系统可以处理重试和重复的请求，而无需执行额外的逻辑或复杂的状态管理。
+  增强了可靠性：幂等性有助于服务以一致的方式处理多个相同的请求，从而降低意外副作用或重复记录的风险。这在分布式系统中尤其重要，在此类系统中，网络故障和重试很常见。
+  提高了数据一致性：由于同一个请求会产生相同的响应，因此幂等性有助于保持分布式系统间的数据一致性。这对于维护事务和操作的完整性至关重要。
+  错误处理：幂等性令牌使错误处理变得更加简单。如果客户端由于问题而未收到响应，则它可以使用相同的幂等性令牌安全地重新发送请求。
+  操作透明度：通过幂等性，可以更好地进行监控和日志记录。服务可以使用其幂等性令牌记录请求，这可以更轻松地跟踪和调试问题。
+  简化了 API 合约：它可以简化客户端和服务器端系统之间的合约，并减少对错误数据处理的担忧。

 **在未建立这种最佳实践的情况下暴露的风险等级：**中 

## 实施指导
<a name="implementation-guidance"></a>

 在分布式系统中，至多（客户端仅发起一个请求）或至少（客户端持续发起请求直到确认成功）执行某项操作一次相对简单。然而，*确切一次* 实施此行为则具有挑战性。为了实现这一点，客户端应该为每个请求生成并提供幂等性令牌。

 通过使用幂等性令牌，服务可以区分新请求和重复的请求。当服务收到带有幂等性令牌的请求时，它会检查该令牌是否已被使用。如果该令牌已被使用，则该服务会检索并返回存储的响应。如果令牌是新的，则服务会处理请求，将响应与令牌一起存储，然后返回响应。这种机制使所有响应都是幂等的，从而提高了分布式系统的可靠性和一致性。

 幂等性也是事件驱动型架构的一项重要行为。这些架构通常由消息队列提供支持，例如 Amazon SQS、Amazon MQ、Amazon Kinesis Streams 或 Amazon Managed Streaming for Apache Kafka（MSK）。在某些情况下，只发布一次的消息可能会意外地传送多次。当发布者生成幂等性令牌并将其包含在消息中时，它要求对收到的任何重复消息的处理不会导致对同一消息执行重复的操作。使用者应跟踪收到的每个令牌，并忽略包含重复令牌的消息。

 服务和使用者还应将收到的幂等性令牌传递给它调用的任何下游服务。处理链中的每个下游服务都同样负责确保实施幂等性，以避免多次处理消息的副作用。

### 实施步骤
<a name="implementation-steps"></a>

1.  **确定幂等操作** 

    确定哪些操作需要幂等性。这些操作通常包括 POST、PUT 和 DELETE HTTP 方法以及数据库插入、更新或删除操作。不变异状态的操作（例如只读查询）通常不需要幂等性，除非它们有副作用。

1.  **使用唯一标识符** 

    在发送者发送的每个幂等操作请求中包含一个唯一的令牌，既可以直接在请求中，也可以作为其元数据的一部分（例如，HTTP 标头）。这可让接收者识别和处理重复的请求或操作。通常用于令牌的标识符包括 [Universally Unique Identifiers (UUIDs)](https://datatracker.ietf.org/doc/html/rfc9562) 和 [K-Sortable Unique Identifiers (KSUIDs)](https://github.com/segmentio/ksuid)。

1.  **跟踪和管理状态** 

    维护工作负载中每个操作或请求的状态。这可以通过将幂等性令牌和相应的状态（例如待处理、已完成或失败）存储在数据库、缓存或其它持久存储中来实现。此状态信息可让工作负载识别和处理重复的请求或操作。

    如果需要，可通过使用适当的并发控制机制（例如锁定、事务或乐观并发控制）来保持一致性和原子性。这包括记录幂等令牌以及运行与为请求提供服务相关联的所有变异操作的过程。这有助于防止竞争条件并验证幂等操作是否正确运行。

    定期从数据存储中移除旧的幂等性令牌来管理存储和性能。如果存储系统支持此操作，请考虑对数据使用过期时间戳（通常称为生存时间或 TTL 值）。重用幂等性令牌的可能性会随时间推移而降低。

    通常用于存储幂等性令牌和相关状态的常见 AWS 存储选项包括：
   +  **Amazon DynamoDB**：DynamoDB 是一项 NoSQL 数据库服务，可提供低延迟性能和高可用性，因此非常适合存储与幂等性相关的数据。DynamoDB 的键值和文档数据模型支持高效存储和检索幂等性令牌和关联的状态信息。如果应用程序在插入幂等性令牌时设置了 TTL 值，则 DynamoDB 也可以自动使这些令牌过期。
   +  **Amazon ElastiCache**：ElastiCache 能够以高吞吐量、低延迟和低成本存储幂等性令牌。如果应用程序在插入幂等性令牌时设置了 TTL 值，ElastiCache（Redis）和 ElastiCache（Memcached）也可以自动使这些令牌过期。
   +  **Amazon Relational Database Service（RDS）**：可以使用 Amazon RDS 存储幂等性令牌和相关状态信息，特别是在应用程序已经将关系数据库用于其它用途的情况下。
   +  **Amazon Simple Storage Service（S3）**：Amazon S3 是一项高度可扩展和耐用的对象存储服务，可用于存储幂等性令牌和相关元数据。S3 的版本控制功能对于维护幂等操作的状态特别有用。存储服务的选择通常取决于诸如因素，例如：与幂等性相关的数据量、所需的性能特征、对耐久性和可用性的需求，以及幂等性机制如何与整体工作负载架构集成。

1.  **实施幂等操作** 

    将 API 和工作负载组件设计为幂等的。将幂等性检查纳入工作负载组件。在处理请求或执行操作之前，请检查是否已经处理了唯一标识符。如果已处理，则返回之前的结果，而不是再次执行该操作。例如，如果客户端发送一个创建用户的请求，请检查是否已存在具有相同唯一标识符的用户。如果该用户存在，则应返回现有用户信息，而不是创建新用户。同样，如果队列使用者收到带有重复幂等性令牌的消息，则该使用者应忽略该消息。

    创建全面的测试套件来验证请求的幂等性。它们应涵盖各种各样的场景，例如成功的请求、失败的请求和重复的请求。

    如果工作负载利用 AWS Lambda 函数，请考虑使用 Powertools for AWS Lambda。Powertools for AWS Lambda 是一个开发人员工具包，有助于在使用 AWS Lambda 函数时实施无服务器最佳实践并提高开发人员速度。特别是，它提供了一个实用程序，可将 Lambda 函数转换为可以安全重试的幂等操作。

1.  **清晰地传达幂等性** 

    记录 API 和工作负载组件，以清晰地传达操作的幂等性质。这有助于客户了解预期行为以及如何可靠地与工作负载进行交互。

1.  **监控和审计** 

    实施监控和审计机制，以检测与响应的幂等性相关的任何问题，例如意外的响应变化或过多的重复请求处理。这有助于您检测和调查工作负载中的任何问题或意外行为。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL05-BP03 控制与限制重试调用](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_limit_retries.html) 
+  [REL06-BP01 为工作负载监控全部组件（生成）](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_monitor_aws_resources_monitor_resources.html) 
+  [REL06-BP03 发送通知（实时处理和报警）](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_monitor_aws_resources_notification_monitor.html) 
+  [REL08-BP02 将功能测试作为部署的一部分进行集成](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_tracking_change_management_functional_testing.html) 

 **相关文档：**
+  [The Amazon Builders' Library: Making retries safe with idempotent APIs](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/) 
+  [Amazon Builders' Library：分布式系统相关挑战](https://aws.amazon.com/builders-library/challenges-with-distributed-systems/) 
+  [Amazon Builders' Library：Reliability, constant work, and a good cup of coffee](https://aws.amazon.com/builders-library/reliability-and-constant-work/) 
+  [Amazon Elastic Container Service: Ensuring idempotency](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/ECS_Idempotency.html) 
+  [如何让我的 Lambda 函数保持幂等性？](https://repost.aws/knowledge-center/lambda-function-idempotent) 
+  [Ensuring idempotency in Amazon EC2 API requests](https://docs.aws.amazon.com/ec2/latest/devguide/ec2-api-idempotency.html) 

 **相关视频：**
+  [Building Distributed Applications with Event-driven Architecture - AWS Online Tech Talks](https://www.youtube.com/watch?v=gA2-eqDVSng&t=1668s) 
+  [AWS re:Invent 2023 - Building next-generation applications with event-driven architecture](https://www.youtube.com/watch?v=KXR17uwLEC8) 
+  [AWS re:Invent 2023 - Advanced integration patterns & trade-offs for loosely coupled systems](https://www.youtube.com/watch?v=FGKGdUiZKto) 
+  [AWS re:Invent 2023 - Advanced event-driven patterns with Amazon EventBridge](https://www.youtube.com/watch?v=6X4lSPkn4ps) 
+  [AWS re:Invent 2018 - Close Loops and Opening Minds: How to Take Control of Systems, Big and Small ARC337 (includes loose coupling, constant work, static stability)](https://youtu.be/O8xLxNje30M) 
+  [AWS re:Invent 2019 - Moving to event-driven architectures (SVS308)](https://youtu.be/h46IquqjF3E) 

 **相关工具：**
+  [Idempotency with AWS Lambda Powertools (Java)](https://docs.powertools.aws.dev/lambda/java/utilities/idempotency/) 
+  [Idempotency with AWS Lambda Powertools (Python)](https://docs.powertools.aws.dev/lambda/python/latest/utilities/idempotency/) 
+  [AWS Lambda Powertools GitHub page](https://github.com/aws-powertools/) 

# 在分布式系统中设计交互以减少或承受故障
<a name="design-interactions-in-a-distributed-system-to-mitigate-or-withstand-failures"></a>

 分布式系统依赖于通信网络实现组件（例如服务器或服务）的互联。尽管这些网络中存在数据丢失或延迟，但是您的工作负载必须可靠运行。分布式系统组件的运行方式不得对其他组件或工作负载产生负面影响。这些最佳实践使工作负载能够承受压力或故障，从中更快地恢复，并且降低此类损坏的影响。其结果是缩短平均恢复时间（MTTR）。

 这些最佳实践可以防止故障并缩短平均故障间隔时间 (MTBF)。

**Topics**
+ [REL05-BP01 实施优雅降级以将适用的硬依赖关系转换为软依赖关系](rel_mitigate_interaction_failure_graceful_degradation.md)
+ [REL05-BP02 限制请求](rel_mitigate_interaction_failure_throttle_requests.md)
+ [REL05-BP03 控制与限制重试调用](rel_mitigate_interaction_failure_limit_retries.md)
+ [REL05-BP04 快速失效机制和限制队列](rel_mitigate_interaction_failure_fail_fast.md)
+ [REL05-BP05 设置客户端超时](rel_mitigate_interaction_failure_client_timeouts.md)
+ [REL05-BP06 尽可能使系统为无状态](rel_mitigate_interaction_failure_stateless.md)
+ [REL05-BP07 实施紧急杠杆](rel_mitigate_interaction_failure_emergency_levers.md)

# REL05-BP01 实施优雅降级以将适用的硬依赖关系转换为软依赖关系
<a name="rel_mitigate_interaction_failure_graceful_degradation"></a>

即使依赖项不可用，应用程序组件也应继续执行其核心功能。应用程序组件可以提供稍微陈旧的数据、替代数据，甚至没有数据。这可确保在提供核心业务价值的同时，将局部故障对整体系统功能造成的障碍减至最少。

 **期望结果：**某个组件的依赖项运行状况不佳时，该组件仍可在性能降低的条件下运行。组件的故障模式应视为正常运行。工作流在设计时，应确保此类故障不会导致完全失败，或者至少实现可预测和可恢复的状态。

 **常见反模式：**
+  未确定所需的核心业务功能。即使在依赖项故障期间也不测试组件是否正常运行。
+  不论是出错时，还是当多个依赖项中只有一个不可用且仍可以返回部分结果时，不提供任何数据。
+  在事务部分失败时造成不一致的状态。
+  没有替代方法用于访问中央 Parameter Store。
+  在刷新失败时，使本地状态失效或清空，而没有考虑这样做的后果。

 **建立此最佳实践的好处：**优雅降级可以提高整个系统的可用性，即使在故障期间也能保持最重要功能的功能。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 实施优雅降级有助于最大限度地减少依赖项故障对组件功能的影响。理想情况下，组件检测依赖项故障，并以对其他组件或客户影响最小的方式解决这些故障。

 为优雅降级设计架构意味着在依赖项设计期间，需要考虑潜在的故障模式。对于每种故障模式，都要有办法向调用方或客户提供组件的大部分功能，或者至少提供最关键的功能。这些注意事项可以作为额外的要求进行测试和验证。理想情况下，即使一个或多个依赖项出现故障，一个组件也能够以可接受的方式执行其核心功能。

 这既是商业议题，也是技术议题。所有业务要求都很重要，应尽可能满足。但是，确定在无法满足所有要求时会出现什么情况，这种做法同样很有意义。系统可以设计为具备可用性和一致性，但是如果必须放弃一个要求，那么哪个要求更重要？ 对于付款处理而言，可能一致性更重要。对于实时应用程序，可能可用性更重要。对于面向客户的网站，这个回答可能取决于客户的期望值。

 其具体的意义取决于组件的要求，以及将什么功能视为其核心功能。例如：
+  在登录页面上，电子商务网站可能会显示来自多个不同系统的数据，例如个性化推荐、最热销的产品和客户订单状态。当一个上游系统出现故障时，合理的做法是显示其余的所有信息，而不是向客户显示一个错误页面。
+  对于执行批量写入的组件，如果某个单独的操作失败，它仍应继续执行批处理。实施重试机制应该很简单。要实施重试机制，可以向调用方返回哪些操作成功、哪些操作失败的信息，或者将失败的请求放入死信队列中来实施异步重试。同时还应记录有关失败操作的信息。
+  处理事务的系统必须确保，要么执行了所有更新，要么未执行任何更新。对于分布式事务，在同一个事务后面的操作失败时，可以使用 Sega 模式来回滚先前的操作。这里的核心功能是保持一致性。
+  时间关键型系统应能够处理未及时响应的依赖项。在这些情况下，可以使用断路器模式。当来自依赖项的响应开始超时时，系统可以切换为关闭状态，不进行额外的调用。
+  应用程序可以从 Parameter Store 中读取参数。创建具有默认参数集的容器镜像，并在 Parameter Store 不可用时使用这些镜像，这种做法会很有用。

 请注意，需要对组件出现故障时所采取的途径进行测试，而且这一途径应该比主要途径简单得多。通常，[应避免使用回退策略](https://aws.amazon.com/builders-library/avoiding-fallback-in-distributed-systems/)。

## 实施步骤
<a name="implementation-steps"></a>

 确定外部和内部依赖项。考虑这些依赖项可能出现什么样的故障。思考能在故障期间尽力减少对上游和下游系统以及客户的负面影响的方法。

 以下是依赖项列表以及在依赖项故障时如何优雅降级：

1.  **依赖项部分故障：**一个组件可以向下游系统发出多个请求，这可以是向一个系统发出多个请求，也可以是向多个系统发出一个请求。根据具体的业务环境，可能需要采用不同的处理方式（有关更多详细信息，请参阅“实施指导”中的示例）。

1.  **下游系统因高负载无法处理请求：**如果对下游系统的请求持续失败，则继续重试就没有意义了。这可能会对已经过载的系统造成额外负载，使得系统更难于恢复。这时可以使用断路器模式，该模式监视对下游系统的失败调用。如果大量调用失败，它会停止向下游系统发送更多请求，仅不定期让调用通过，以测试下游系统是否再次可用。

1.  **Parameter Store 不可用：**要转换 Parameter Store，可以使用容器或机器映像中包含的软依赖项缓存或合理默认值。请注意，这些默认值需要保持为最新并包含在测试套件中。

1.  **监控服务或其他非功能性依赖项不可用：**如果某个组件间歇性地无法将日志、指标或跟踪发送到中央监控服务，通常最好还是正常执行业务功能。长时间静默地不进行日志记录或不推送指标通常不可接受。此外，某些应用场景可能需要完整的审核条目才能满足合规性要求。

1.  **关系数据库的主实例可能不可用**：与几乎所有关系数据库一样，Amazon Relational Database Service 只能有一个主写入器实例。对于写入工作负载，这会造成单点故障，并增加扩缩的难度。使用多可用区配置来实现高可用性，或者使用 Amazon Aurora Serverless 无服务器架构来实现更好的扩展能力，可以部分缓解这种情况。对于非常高的可用性要求，完全不依赖于主写入器是有意义的。对于只读查询，可以使用只读副本，这提供了冗余和横向扩展能力，而不仅仅是纵向扩展。对写入操作可以进行缓冲，例如缓冲在 Amazon Simple Queue Service 队列中，这样即使主写入器暂时不可用，仍然可以接受来自客户的写入请求。

## 资源
<a name="resources"></a>

 **相关文档：**
+  [Amazon API Gateway：限制对 API 的请求以提高吞吐量](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html) 
+  [CircuitBreaker (summarizes Circuit Breaker from “Release It\$1” book)](https://martinfowler.com/bliki/CircuitBreaker.html) 
+  [Error Retries and Exponential Backoff in AWS](https://docs.aws.amazon.com/general/latest/gr/api-retries.html) 
+  [Michael Nygard “Release It\$1 Design and Deploy Production-Ready Software”](https://pragprog.com/titles/mnee2/release-it-second-edition/) 
+  [Amazon Builders' Library：避免在分布式系统中回退](https://aws.amazon.com/builders-library/avoiding-fallback-in-distributed-systems) 
+  [Amazon Builders' Library：避免无法克服的队列积压](https://aws.amazon.com/builders-library/avoiding-insurmountable-queue-backlogs) 
+  [Amazon Builders' Library：缓存挑战和策略](https://aws.amazon.com/builders-library/caching-challenges-and-strategies/) 
+  [Amazon Builders' Library：超时、重试和抖动回退](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 

 **相关视频：**
+  [Retry, backoff, and jitter: AWS re:Invent 2019: Introducing The Amazon Builders' Library (DOP328)](https://youtu.be/sKRdemSirDM?t=1884) 

# REL05-BP02 限制请求
<a name="rel_mitigate_interaction_failure_throttle_requests"></a>

限制请求，防范因需求意外增加而导致的资源耗尽情况。系统将处理未超过限制速率的请求，而超过所定义限制的请求将被拒绝，并返回一条消息，指出请求已受限制。

 **期望结果：**使用请求限制可以缓解客户流量突增、泛洪攻击或重试风暴所造成的大量容量峰值情况，让工作负载能够继续正常处理支持的请求量。

 **常见反模式：**
+  未实施 API 端点限制，或者未考虑预期容量即保留默认值。
+  API 端点未经过负载测试，也未测试节流限制。
+  限制请求速率而未考虑请求大小或复杂性。
+  测试最大请求速率或最大请求大小，但未同时测试两者。
+  资源预置的限制与测试中确定的限制不同。
+  尚未为应用程序到应用程序的（A2A）API 使用者配置或考虑使用量计划。
+  横向扩展的队列使用者没有配置最大并发设置。
+  没有基于每个 IP 地址实施速率限制。

 **建立此最佳实践的好处：**在遇到意外的容量峰值时，设置了节流限制的工作负载能够正常运行，并成功处理已接受的请求负载。API 和队列上突然或持续出现的请求峰值会受到限制，不会耗尽请求处理资源。速率限制会限制单独的请求者，这样来自单个 IP 地址或 API 使用者的大量流量就不会耗尽资源，从而不会影响其他使用者。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 服务应设计为处理已知的请求容量；这种容量可以通过负载测试来确立。如果请求到达速率超过限制，则会发出相应的响应，表示请求已被限制。这让使用者可以处理错误并稍后重试。

 当您的服务需要实施节流时，可以考虑实施令牌存储桶算法，每个令牌对应于一个请求。令牌按照每秒的限制速率重新填充，并按照每个请求一个令牌的模式异步清空。

![\[描述令牌存储桶算法的图表。\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/reliability-pillar/images/token-bucket-algorithm.png)


 

 [Amazon API Gateway](https://aws.amazon.com/api-gateway/) 根据账户和区域限制实施令牌存储桶算法，可通过使用量计划为每个客户端配置。此外，[Amazon Simple Queue Service（Amazon SQS）](https://aws.amazon.com/sqs/)和 [Amazon Kinesis](https://aws.amazon.com/kinesis/) 可以缓冲请求来稳定请求速率，并允许对可以处理的请求实施更高的节流速率。最后，您可以使用 [AWS WAF](https://aws.amazon.com/waf/) 实施速率限制，限制产生异常高负载的特定 API 使用者。

## 实施步骤
<a name="implementation-steps"></a>

 您可以为 API 配置 API Gateway 节流限制，并在超过限制时返回 `429 Too Many Requests` 错误。您可以将 AWS WAF 与 AWS AppSync 和 API Gateway 端点结合使用，根据各个 IP 地址来启用速率限制。此外，如果系统能够接受异步处理，则可以将消息放入队列或流中，借此加快对服务客户端的响应，这样便可以突增到更高的限制速率。

 采用异步处理，在将 Amazon SQS 配置为 AWS Lambda 的事件源时，您可以[配置最大并发数](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-max-concurrency)，避免高事件速率消耗工作负载或账户中其他服务所需的可用账户并发执行配额。

 虽然 API Gateway 提供了令牌存储桶的托管实施，但在无法使用 API Gateway 的情况下，您可以针对服务利用具体语言的令牌存储桶开源实施（参见“资源”中的相关示例）。
+  了解每个区域的账户级别、每个阶段的 API 和每个使用计划级别的 API 密钥的 [API Gateway 节流限制](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html)，并进行配置。
+  对 API Gateway 和 AWS AppSync 端点应用 [AWS WAF 速率限制规则](https://aws.amazon.com/blogs/security/three-most-important-aws-waf-rate-based-rules/)，防范泛洪并阻止恶意 IP。对于 A2A 使用者，也可以在 AWS AppSync API 密钥上配置速率限制规则。
+  对于 AWS AppSync API，请考虑所需节流控制是否超过速率限制；如果超过，则在 AWS AppSync 端点前面配置 API Gateway。
+  在将 Amazon SQS 队列设置为 Lambda 队列使用者的触发器时，请将[最大并发数](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-max-concurrency)设置为足以满足服务级别目标，但不会消耗会影响其他 Lambda 函数的并发限制的值。通过 Lambda 使用队列时，请考虑为相同账户和区域中的其他 Lambda 函数设置预留并发度。
+  将 API Gateway 与 Amazon SQS 或 Kinesis 的原生服务集成结合使用可缓冲请求。
+  如果无法使用 API Gateway，请查看具体语言的库，以便为工作负载实施令牌存储桶算法。查看示例部分，然后自行研究找出合适的库。
+  对您计划设置的限制或者您计划允许增加的限制进行测试，并记录测试后的限制值。
+  不要将限制值提高到超出您在测试中确立的限制值。增加限制时，请先确认预置的资源是否已经等于或大于测试场景中预置的资源，然后再进行增加。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL04-BP03 持续工作](rel_prevent_interaction_failure_constant_work.md) 
+  [REL05-BP03 控制与限制重试调用](rel_mitigate_interaction_failure_limit_retries.md) 

 **相关文档：**
+  [Amazon API Gateway：限制对 API 的请求以提高吞吐量](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html) 
+ [AWS WAF: Rate-based rule statement ](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html)
+ [Introducing maximum concurrency of AWS Lambda when using Amazon SQS as an event source](https://aws.amazon.com/blogs/compute/introducing-maximum-concurrency-of-aws-lambda-functions-when-using-amazon-sqs-as-an-event-source/)
+ [AWS Lambda: Maximum Concurrency](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-max-concurrency)

 **相关示例：**
+ [The three most important AWS WAF rate-based rules](https://aws.amazon.com/blogs/security/three-most-important-aws-waf-rate-based-rules/)
+ [Java Bucket4j](https://github.com/bucket4j/bucket4j)
+ [Python token-bucket](https://pypi.org/project/token-bucket/)
+ [Node token-bucket](https://www.npmjs.com/package/tokenbucket)
+ [.NET System Threading Rate Limiting](https://www.nuget.org/packages/System.Threading.RateLimiting)

 **相关视频：**
+ [Implementing GraphQL API security best practices with AWS AppSync](https://www.youtube.com/watch?v=1ASMLeJ_15U)

 **相关工具：**
+ [Amazon API Gateway](https://aws.amazon.com/api-gateway/)
+ [AWS AppSync](https://aws.amazon.com/appsync/)
+ [Amazon SQS](https://aws.amazon.com/sqs/)
+ [Amazon Kinesis](https://aws.amazon.com/kinesis/)
+ [AWS WAF](https://aws.amazon.com/waf/)
+ [AWS 上的虚拟等候室](https://aws.amazon.com/solutions/implementations/virtual-waiting-room-on-aws/)

# REL05-BP03 控制与限制重试调用
<a name="rel_mitigate_interaction_failure_limit_retries"></a>

使用指数回退来重试请求，每次重试之间的间隔会逐渐延长。在两次重试之间引入抖动来随机调整重试间隔。限制最大重试次数。

 **期望结果：**分布式软件系统中的常见组件包括服务器、负载均衡器、数据库和 DNS 服务器。在正常运行期间，这些组件对请求的响应可能是临时错误或者受限制错误，也能是无论如何重试都会持续存在的错误。当客户端向服务发出请求时，请求会消耗资源，包括内存、线程、连接、端口或任何其他有限的资源。控制和限制重试策略用于释放资源并最大限度地减少资源消耗，这样就可以避免承受压力的系统组件不堪重负。

 当客户端请求超时或收到错误响应时，客户端应决定是否重试。如果进行重试，则会按照最大重试次数值，采用指数回退和抖动方法进行重试。因此，后端服务和进程可以缓解负载并缩短自我修复时间，从而加快恢复速度并成功处理服务请求。

 **常见反模式：**
+  实施重试，但没有添加指数回退、抖动和最大重试次数值。指数回退和抖动有助于避免因无意间按照相同间隔协调进行重试，从而导致的人为流量峰值。
+  实施重试但没有测试重试的效果，或者假设 SDK 中已经内置了重试而不测试重试场景。
+  无法理解依赖项发布的错误代码，导致重试所有错误，包括那些有明确原因的错误，这些错误指出缺乏权限、配置错误或其他预计需要手动干预才能解决的情况。
+  没有解决可观测性实践，包括监控反复出现的服务故障并发出警报，以便了解和解决潜在问题。
+  在内置或第三方重试功能便已足够时，开发自定义重试机制。
+  在应用程序堆栈的多层进行重试，而重试方法导致重试尝试复杂化，进一步加剧了重试风暴中的资源消耗。一定要了解这些错误对您的应用程序以及所依赖的依赖项有何影响，然后仅在一个级别实施重试。
+  重试非幂等的服务调用，导致意外的副作用，例如重复的结果。

 **建立此最佳实践的好处：**重试有助于客户端在请求失败时获得预期的结果，但也会消耗更多的服务器时间来获取所需的成功响应。当故障比率很低或者是临时性故障时，重试效果很好。当故障是由资源过载导致时，重试会导致情况进一步恶化。通过在客户端重试中添加指数回退和抖动，服务器可以从因资源过载导致的故障中恢复。抖动可避免请求同时出现造成峰值，指数回退可以减少因在正常请求负载中增添重试而导致的负载上升。最后，务必要配置最大重试次数或用时，避免产生导致亚稳态故障的积压。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 控制与限制重试调用。在逐渐延长的间隔以后使用指数回退进行重试。引入抖动来随机调整重试间隔，并限制重试的最大次数。

 默认情况下，一些 AWS SDK 实施重试和指数回退。在适用于工作负载的情况下，使用这些内置 AWS 实施。在调用幂等性服务时，以及重试可以提高客户端可用性时，在工作负载中实施类似的逻辑。根据应用场景确定超时以及何时停止重试。为重试应用场景构建和演练测试场景。

## 实施步骤
<a name="implementation-steps"></a>
+  对于应用程序所依赖的服务，确定应用程序堆栈中最适合实施重试的层。
+  请注意，现有的 SDK 会针对您选择的语言，实施采用了指数回退和抖动方法的成熟重试策略，相比您自己编写重试实施，使用这些实施方法会更好。
+  请先验证[服务是否具有幂等性](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/)，再实施重试。实施重试后，请确保在生产环境中进行测试，并定期进行演练。
+  调用 AWS 服务 API 时，请使用 [AWS SDK](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html) 和 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-retries.html)，并了解重试配置选项。确定默认值是否适用于应用场景，进行测试，并根据需要进行调整。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL04-BP04 使变异操作幂等](rel_prevent_interaction_failure_idempotent.md) 
+  [REL05-BP02 限制请求](rel_mitigate_interaction_failure_throttle_requests.md) 
+  [REL05-BP04 快速失效机制和限制队列](rel_mitigate_interaction_failure_fail_fast.md) 
+  [REL05-BP05 设置客户端超时](rel_mitigate_interaction_failure_client_timeouts.md) 
+  [REL11-BP01 监控工作负载的所有组件以检测故障](rel_withstand_component_failures_monitoring_health.md) 

 **相关文档：**
+  [Error Retries and Exponential Backoff in AWS](https://docs.aws.amazon.com/general/latest/gr/api-retries.html) 
+  [Amazon Builders' Library：超时、重试和抖动回退](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 
+ [ Exponential Backoff and Jitter ](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)
+ [Making retries safe with idempotent APIs](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/)

 **相关示例：**
+ [Spring Retry](https://github.com/spring-projects/spring-retry)
+ [Resilience4j Retry](https://resilience4j.readme.io/docs/retry)

 **相关视频：**
+  [Retry, backoff, and jitter: AWS re:Invent 2019: Introducing The Amazon Builders' Library (DOP328)](https://youtu.be/sKRdemSirDM?t=1884) 

 **相关工具：**
+ [AWS SDKs and Tools: Retry behavior](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)
+ [AWS Command Line Interface: AWS CLI retries](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-retries.html)

# REL05-BP04 快速失效机制和限制队列
<a name="rel_mitigate_interaction_failure_fail_fast"></a>

当服务无法成功响应请求时，可采用快速失效机制。这样可释放与请求关联的资源，并允许该服务在资源不足的情况下进行恢复。快速失效机制一种成熟的软件设计模式，可用于在云端构建高度可靠的工作负载。队列也是一种成熟的企业集成模式，其能够实现平稳的负载，并在能够容忍异步处理的情况下，使得客户端能够释放资源。如果某个服务在正常条件下能够成功响应，但在请求速率过高时失败，请使用队列来缓冲请求。不过，不要允许出现较长的队列积压，否则可能导致处理已被客户端放弃的过时请求。

 **期望结果：**当系统遇到资源争用、超时、异常或灰色故障等情况，导致无法实现服务等级目标时，快速失效机制策略可以加快系统恢复速度。如果系统必须承受流量峰值并能够适应异步处理，就可以使用队列来缓冲对后端服务的请求，让客户端可以快速释放请求，从而提高可靠性。在将请求缓冲到队列中时，系统将实施队列管理策略来避免出现无法克服的积压。

 **常见反模式：**
+  实施消息队列，但不配置死信队列（DLQ）或 DLQ 数量警报来检测系统出现故障的时间。
+  不测量队列中消息的时限（关于延迟的度量）来了解队列使用者何时落后或者出错并导致重试。
+  当业务不需要再存在时，处理积压的消息没有任何价值，但不从队列中清除这些消息。
+  当后进先出（LIFO）队列可以更好地满足客户端需求时，配置先进先出（FIFO）队列，例如，在不需要严格排序并且处理积压内容会延误所有新的和注重时效性的请求时，先进先出队列会导致所有客户端出现违反服务等级协议的情况。
+  向客户端公开内部队列，而不是公开那些管理工作摄入并将请求放入内部队列的 API。
+  将过多的工作请求类型合并到一个队列中，这会导致在一个队列中分配对多种请求类型的资源需求，进而会加剧积压情况。
+  在同一个队列中处理复杂请求和简单请求，但这些请求具有不同的监控、超时和资源分配需求。
+  不验证输入，也不使用断言在软件中实施快速失效机制，这些机制可将异常上报到更高级别的组件来轻松处理错误。
+  不从请求路由中移除出现故障的资源，尤其是在由于崩溃和重启、间歇性依赖项故障、容量减少或网络数据包丢失，导致同时出现成功和失败的灰色故障时。

 **建立此最佳实践的好处：**采用快速失效机制的系统更容易调试和修复，通常在将版本发布到生产环境之前，在编码和配置阶段就会暴露问题。采用有效排队策略的系统在面对流量高峰和间歇性系统故障的情况时，能够提供更出色的韧性和可靠性。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 快速失效机制策略能够通过编码形式构建到软件解决方案中，也能够在基础设施中配置。除了快速失效机制之外，还可通过队列这种简单而强大的架构技术来解耦系统组件，实现平稳的负载。[Amazon CloudWatch：](https://aws.amazon.com/cloudwatch/)提供监控故障和发出警报的功能。在确定系统出现故障时，可以调用缓解策略，包括从受损资源进行失效转移。当系统使用 [Amazon SQS](https://aws.amazon.com/sqs/) 和其他队列技术实施队列来实现平稳的负载时，须考虑如何管理队列积压以及消息使用故障。

## 实施步骤
<a name="implementation-steps"></a>
+  在软件中实施编程式断言或特定指标，并将其用于明确发出关于系统问题的警报。Amazon CloudWatch 有助于根据应用程序日志模式和 SDK 检测工具来创建指标和警报。
+  使用 CloudWatch 指标和警报从受损资源进行故障转移，这些受损资源会增加处理延迟或者在处理请求时反复失败。
+  要使用异步处理，您可以设计 API 来接受请求，并使用 Amazon SQS 将请求附加到内部队列，然后向生成消息的客户端发送成功消息，这样客户端就可以释放资源，并继续处理其他工作，同时后端队列使用者可以处理请求。
+  在每次从队列中删除消息时，通过将现在的时间戳与消息时间戳进行比较来生成 CloudWatch 指标，从而测量和监控队列处理延迟。
+  如果故障导致无法成功处理消息，或者有大量的流量高峰无法按照服务等级协议的要求处理，则将较旧或过多的流量转到溢出队列。这样便可以优先处理新的工作，在有可用容量时再处理较早的工作。这种技术与 LIFO 处理有相似之处，使得可以对所有新工作进行正常的系统处理。
+  使用死信或再驱动队列，将无法处理的消息从积压中移至另一个位置，供以后研究和解决 
+  您可以重试，或者在允许的情况下，通过将现在的时间戳与消息时间戳进行比较，丢弃与发出请求的客户端不再相关的消息，以此来删除旧消息。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL04-BP02 实施松耦合的依赖关系](rel_prevent_interaction_failure_loosely_coupled_system.md) 
+  [REL05-BP02 限制请求](rel_mitigate_interaction_failure_throttle_requests.md) 
+  [REL05-BP03 控制与限制重试调用](rel_mitigate_interaction_failure_limit_retries.md) 
+  [REL06-BP02 定义与计算指标（聚合）](rel_monitor_aws_resources_notification_aggregation.md) 
+  [REL06-BP07 对系统中的请求进行端到端跟踪监控](rel_monitor_aws_resources_end_to_end.md) 

 **相关文档：**
+ [避免无法克服的队列积压](https://aws.amazon.com/builders-library/avoiding-insurmountable-queue-backlogs/)
+  [Fail Fast](https://www.martinfowler.com/ieeeSoftware/failFast.pdf) 
+ [如何防止我的 Amazon SQS 队列中日益积压的消息？](https://repost.aws/knowledge-center/sqs-message-backlog)
+ [Elastic Load Balancing: Zonal Shift](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/zonal-shift.html)
+ [Amazon Application Recovery Controller: Routing control for traffic failover](https://docs.aws.amazon.com/r53recovery/latest/dg/getting-started-routing-controls.html)

 **相关示例：**
+ [Enterprise Integration Patterns: Dead Letter Channel](https://www.enterpriseintegrationpatterns.com/patterns/messaging/DeadLetterChannel.html)

 **相关视频：**
+  [AWS re:Invent 2022 – Operating highly available Multi-AZ applications](https://www.youtube.com/watch?v=mwUV5skJJ0s) 

 **相关工具：**
+ [Amazon SQS](https://aws.amazon.com/sqs/)
+ [Amazon MQ](https://aws.amazon.com/amazon-mq/)
+ [AWS IoT Core](https://aws.amazon.com/iot-core/)
+ [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/)

# REL05-BP05 设置客户端超时
<a name="rel_mitigate_interaction_failure_client_timeouts"></a>

您应适当设置连接和请求的超时，对其进行系统性验证，不要依赖默认值，因为默认值并不了解具体的工作负载情况。

 **期望结果：**客户端超时应考虑当完成请求需要超长时间时，与等待请求相关的客户端、服务器和工作负载成本。由于无法知晓任何超时的确切原因，因此客户端必须运用对服务的了解，预测可能的原因和相应的超时时间。

 客户端会根据配置的值连接超时。遇到超时后，客户端会决定回退并重试，或者打开[断路器](https://martinfowler.com/bliki/CircuitBreaker.html)。这些模式可避免发出会加剧底层错误状况的请求。

 **常见反模式：**
+  不了解系统超时或默认超时。
+  不了解正常的请求完成时间。
+  不了解完成请求需要超长时间的可能原因，也不了解与等待完成这些请求相关的客户端、服务器或工作负载性能成本。
+  不了解网络受损只要在达到超时后就可能会导致请求失败，也不了解未采用更短的超时时间而招致的客户端和工作负载性能成本。
+  未针对连接和请求来测试超时场景。
+  将超时设置得过高，这会导致等待时间过长并增加资源使用。
+  将超时设置得过低，会导致人为故障。
+  忽略处理远程调用超时错误的模式，例如断路器和重试。
+  不考虑监控服务调用错误率、延迟的服务等级目标和延迟异常值。这些指标能够提供关于过长或不合理超时的洞察信息 

 **建立此最佳实践的好处：**配置了远程调用超时，且系统在设计上可以轻松处理超时，这样在远程调用响应异常缓慢时能够节省资源，且服务客户端可以轻松处理超时错误。

 **在未建立这种最佳实践的情况下暴露的风险等级：**高 

## 实施指导
<a name="implementation-guidance"></a>

 针对所有服务依赖项调用以及一般情况下的所有跨流程调用，设置连接超时和请求超时。许多框架具有内置超时功能，但仍需谨慎，因为一些超时的默认值为无限值，或者高于您的服务目标可以接受的值。过高的值会降低超时的实用性，因为客户端等待超时发生时，系统会继续消耗资源。过低的值可能会重试请求过多次，因而导致后端流量增加以及延迟变长。在有些情况下，由于要对全部请求进行重试，从而可能导致完全中断。

 在确定超时策略时，请考虑以下几点：
+  由于请求的内容、目标服务受损或网络分区故障，处理请求所需的时间可能比正常时间要长。
+  请求如果具有成本异常高的内容，就可能会消耗不必要的服务器和客户端资源。在这种情况下，让这些请求超时而不进行重试可以节省资源。服务还应利用限制和服务器端超时，来保护自身免受成本异常高的内容的侵害。
+  如果由于服务受损而导致请求用时超长，则可以使请求超时并进行重试。请求和重试的服务成本需要考虑在内，但如果原因是局部受损，则重试的成本可能不会太高，而且会减少客户端资源消耗。根据损害的性质，超时还可能会释放服务器资源。
+  如果由于网络未能传输请求或响应，导致请求完成用时很长，则可以使请求超时并进行重试。由于未能传输请求或响应，因此无论超时时间多长，结果都是失败。在这种情况下，超时不会释放服务器资源，但可以释放客户端资源并提高工作负载性能。

 利用重试和断路器等成熟的设计模式，可轻松地处理超时并支持快速失效机制方法。[AWSSDK](https://docs.aws.amazon.com/index.html#sdks) 和 [AWS CLI](https://aws.amazon.com/cli/) 允许配置连接和请求超时，以及使用指数回退和抖动进行重试。[AWS Lambda](https://aws.amazon.com/lambda/) 函数支持超时配置，所以借助 [AWS Step Functions](https://aws.amazon.com/step-functions/)，您可以利用与 AWS 服务和 SDK 的预构建集成，以低代码方式构建断路器。[AWS App Mesh](https://aws.amazon.com/app-mesh/)Envoy 提供超时和断路器功能。

## 实施步骤
<a name="implementation-steps"></a>
+  配置远程服务调用的超时，并利用内置语言超时功能或开源超时库。
+  当您的工作负载使用 AWS SDK 进行调用时，请查看文档以了解具体语言的超时配置。
  + [Python](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html)
  + [PHP](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.DefaultsMode.Configuration.html)
  + [.NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html)
  + [Ruby](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/timeout-duration.html)
  + [Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/best-practices.html#bestpractice5)
  + [Go](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/retries-timeouts/#timeouts)
  + [Node.js](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html)
  + [C\$1\$1](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/client-config.html)
+  在工作负载中使用 AWS SDK 或 AWS CLI 命令时，可通过设置 `connectTimeoutInMillis` 和 `tlsNegotiationTimeoutInMillis` 的 AWS [配置默认值](https://docs.aws.amazon.com/sdkref/latest/guide/feature-smart-config-defaults.html)来配置默认超时值。
+  应用[命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html) `cli-connect-timeout` 和 `cli-read-timeout` 来控制对 AWS 服务的一次性 AWS CLI 命令。
+  监控远程服务调用的超时，并针对持续性错误设置警报，这样您就能够主动处理错误情况。
+  实施对调用错误率、延迟的服务等级目标和延迟异常值的 [CloudWatch Metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html) 和 [CloudWatch 异常检测](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Anomaly_Detection.html)，有助于深入了解如何管理过长或不合理的超时。
+  配置 [Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-timeout-console)的超时时间。
+  处理超时的时候，API Gateway 客户端必须实施自己的重试。对于下游集成，API Gateway 支持 [50 毫秒到 29 秒的集成超时](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#api-gateway-execution-service-limits-table)，并且不会在集成请求超时时重试。
+  实施[断路器](https://martinfowler.com/bliki/CircuitBreaker.html)模式，避免在超时时进行远程调用。打开断路器避免调用失败，并在调用响应正常时关闭断路器。
+  对于基于容器的工作负载，请查看 [App Mesh Envoy](https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html) 功能，以便充分利用内置的超时和断路器。
+  使用 AWS Step Functions，以低代码方式为远程服务调用构建断路器，尤其是在调用 AWS 原生 SDK 和所支持的 Step Functions 集成时，以此简化工作负载。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL05-BP03 控制与限制重试调用](rel_mitigate_interaction_failure_limit_retries.md) 
+  [REL05-BP04 快速失效机制和限制队列](rel_mitigate_interaction_failure_fail_fast.md) 
+  [REL06-BP07 对系统中的请求进行端到端跟踪监控](rel_monitor_aws_resources_end_to_end.md) 

 **相关文档：**
+  [AWS SDK: Retries and Timeouts](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html) 
+  [Amazon Builders' Library：超时、重试和抖动回退](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 
+ [Amazon API Gateway 配额和重要说明](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html)
+ [AWS Command Line Interface: Command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html)
+ [AWS SDK for Java 2.x: Configure API Timeouts](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/best-practices.html#bestpractice5)
+ [AWS Botocore using the config object and Config Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#using-the-config-object)
+ [适用于 .NET 的 AWS SDK: Retries and Timeouts](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html)
+ [AWS Lambda：配置 Lambda 函数选项](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html)

 **相关示例：**
+ [Using the circuit breaker pattern with AWS Step Functions and Amazon DynamoDB](https://aws.amazon.com/blogs/compute/using-the-circuit-breaker-pattern-with-aws-step-functions-and-amazon-dynamodb/)
+ [Martin Fowler: CircuitBreaker](https://martinfowler.com/bliki/CircuitBreaker.html?ref=wellarchitected)

 **相关工具：**
+ [AWS SDK](https://docs.aws.amazon.com/index.html#sdks)
+ [AWS Lambda](https://aws.amazon.com/lambda/)
+ [Amazon SQS](https://aws.amazon.com/sqs/)
+ [AWS Step Functions](https://aws.amazon.com/step-functions/)
+ [AWS Command Line Interface](https://aws.amazon.com/cli/)

# REL05-BP06 尽可能使系统为无状态
<a name="rel_mitigate_interaction_failure_stateless"></a>

 系统应该不需要状态，或者在不同的客户端请求之间卸载状态，磁盘上和内存中本地存储的数据不存在依赖关系。从而支持任意替换服务器，而且不会对可用性产生影响。

 当用户或服务与应用程序进行交互，它们通常会执行一系列交互并构成一次会话。对于用户来说，会话是他们在使用应用程序时持续存在于请求之间的特殊数据。无状态应用程序是无需掌握之前交互而且不会存储会话信息的应用程序。

 若采用无状态设计，则您可以使用无服务器计算服务，如 AWS Lambda 或 AWS Fargate。

 除了服务器替换，无状态应用程序的另一项优点是，由于任何可用的计算资源（如 EC2 实例和 AWS Lambda 函数）都可以处理任何请求，因此它们可以进行横向扩展。

 **建立此最佳实践的好处：**设计为无状态的系统更适合水平扩缩，因为可以根据流量和需求的波动情况增加或删除容量。此类系统还固有故障恢复能力，为应用程序开发提供了灵活性和敏捷性。

 **在未建立这种最佳实践的情况下暴露的风险等级：**中 

## 实施指导
<a name="implementation-guidance"></a>

 让应用程序无状态。无状态应用程序支持水平扩缩，并且可以承受单个节点故障。分析并了解在架构内维持状态的应用程序组件。这有助于您评测过渡到无状态设计的潜在影响。无状态架构会解耦用户数据并分流会话数据。这为独立扩展每个组件提供了灵活性，可以满足不同的工作负载需求，并优化资源利用率。

### 实施步骤
<a name="implementation-steps"></a>
+  确定并了解应用程序中的有状态组件。
+  将用户数据与核心应用程序逻辑分离开来进行管理，以此来解耦数据。
  +  [Amazon Cognito](https://aws.amazon.com/cognito/) 可以使用[身份池](https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-with-identity-pools.html)、[用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-with-cognito-user-pools.html)和 [Amazon Cognito Sync](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-sync.html) 等功能，将用户数据与应用程序代码解耦。
  +  您可以通过将密钥存储在安全的集中位置来使用 [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) 解耦用户数据。这意味着应用程序代码不需要存储密钥，这会令其更加安全。
  +  考虑采用 [Amazon S3](https://aws.amazon.com/s3/) 存储大型非结构化数据，例如图像和文档。应用程序可以在需要时检索这些数据，无需将数据存储在内存中。
  +  使用 [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) 存储用户资料等信息。您的应用程序可以近乎实时地查询这些数据。
+  将会话数据分流到数据库、缓存或外部文件。
  +  [Amazon ElastiCache](https://aws.amazon.com/elasticache/)、Amazon DynamoDB、[Amazon Elastic File System](https://aws.amazon.com/efs/)（Amazon EFS）和 [Amazon MemoryDB](https://aws.amazon.com/memorydb/) 都是可用于分流会话数据的 AWS 服务示例。
+  在确定需要将哪些状态和用户数据保留在所选存储解决方案中之后，设计无状态架构。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL11-BP03 自动修复所有层](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_withstand_component_failures_auto_healing_system.html) 

 **相关文档：**
+  [Amazon Builders' Library：避免在分布式系统中回退](https://aws.amazon.com/builders-library/avoiding-fallback-in-distributed-systems) 
+  [Amazon Builders' Library：避免无法克服的队列积压](https://aws.amazon.com/builders-library/avoiding-insurmountable-queue-backlogs) 
+  [Amazon Builders' Library：缓存挑战和策略](https://aws.amazon.com/builders-library/caching-challenges-and-strategies/) 
+  [AWS 上无状态 Web 层的最佳实践](https://docs.aws.amazon.com/whitepapers/latest/best-practices-wordpress/stateless-web-tier.html) 

# REL05-BP07 实施紧急杠杆
<a name="rel_mitigate_interaction_failure_emergency_levers"></a>

 紧急杠杆是可帮助您的工作负载减轻可用性影响的快速流程。

 紧急杠杆的工作原理是使用已知且经过测试的机制，禁用、节流或更改组件或依赖项的行为。这可以缓解因需求意外增加导致资源耗尽而造成的工作负载损失，并减少工作负载中非关键组件故障的影响。

 **期望结果：**通过实施应急杠杆，您可以建立已知良好的流程，以保持工作负载中关键组件的可用性。在激活紧急杠杆期间，工作负载应进行优雅降级，并继续执行其关键业务功能。有关优雅降级的更多详细信息，请参阅 [REL05-BP01 实施优雅降级以将适用的硬依赖关系转换为软依赖关系](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_graceful_degradation.html)。

 **常见反模式：**
+  非关键依赖关系的故障会影响核心工作负载的可用性。
+  在非关键组件受损时，不测试或验证关键组件的行为。
+  没有为紧急杠杆的激活或停用定义明确的标准。

 **建立此最佳实践的好处：**实施紧急杠杆可以为解析器提供既定的流程来应对意外的需求激增或非关键依赖关系的故障，从而提高工作负载中关键组件的可用性。

 **在未建立这种最佳实践的情况下暴露的风险等级：**中 

## 实施指导
<a name="implementation-guidance"></a>
+  识别工作负载中的关键组件。
+  设计和构建工作负载中的关键组件，使其能够承受非关键组件的故障。
+  进行测试以验证关键组件在非关键组件出现故障期间的行为。
+  定义和监控相关指标或触发器，以启动紧急杠杆程序。
+  定义构成紧急杠杆的（手动或自动）程序。

### 实施步骤
<a name="implementation-steps"></a>
+  识别工作负载中的关键业务组件。
  +  工作负载中的每个技术组件都应与相关业务职能相对应，并评定为关键组件或非关键组件。有关 Amazon 关键和非关键功能的示例，请参阅 [Any Day Can Be Prime Day: How Amazon.com Search Uses Chaos Engineering to Handle Over 84K Requests Per Second](https://community.aws/posts/how-search-uses-chaos-engineering)。
  +  这既是技术决策又是业务决策，而且因组织和工作负载而异。
+  设计和构建工作负载中的关键组件，使其能够承受非关键组件的故障。
  +  在分析依赖项期间，考虑所有潜在的故障模式，并验证您的紧急杠杆机制是否为下游组件提供了关键功能。
+  进行测试以验证关键组件在紧急杠杆激活期间的行为。
  +  避免双模态行为。有关更多详细信息，请参阅 [REL11-BP05 使用静态稳定性来防止双模态行为](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_withstand_component_failures_static_stability.html)。
+  定义和监控相关指标并针对指标发出警报，以便启动紧急杠杆程序。
  +  根据工作负载，找到要监控的正确指标。例如，这些指标可以是延迟，或者是对依赖项请求失败的次数。
+  定义构成紧急杠杆的手动或自动程序。
  +  这可能包括[卸除负载](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/)、[限制请求](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_throttle_requests.html)或实施[优雅降级](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_graceful_degradation.html)等机制。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL05-BP01 实施优雅降级以将适用的硬依赖关系转换为软依赖关系](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_graceful_degradation.html) 
+  [REL05-BP02 限制请求](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_throttle_requests.html) 
+  [REL11-BP05 使用静态稳定性来防止双模态行为](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_withstand_component_failures_static_stability.html) 

 **相关文档：**
+ [自动实现无需干预的安全部署](https://aws.amazon.com/builders-library/automating-safe-hands-off-deployments/)
+  [Any Day Can Be Prime Day: How Amazon.com Search Uses Chaos Engineering to Handle Over 84K Requests Per Second](https://community.aws/posts/how-search-uses-chaos-engineering) 

 **相关视频：**
+ [AWS re:Invent 2020: Reliability, consistency, and confidence through immutability](https://www.youtube.com/watch?v=jUSYnRztttY)