可扩展性设计

Chinese, Simplified
本文地址
https://architect.pub/scalaility-design
SEO Title
scalaility design

【可扩展性】谷歌可扩展和弹性应用的模式

Chinese, Simplified

本文档介绍了一些用于创建具有弹性和可扩展性的应用程序的模式和实践,这是许多现代架构练习的两个基本目标。设计良好的应用程序会随着需求的增加和减少而上下扩展,并且具有足够的弹性以承受服务中断。构建和运行满足这些要求的应用程序需要仔细规划和设计。

可扩展性:调整容量以满足需求


可扩展性是衡量系统通过在系统中添加或删除资源来处理不同数量的工作的能力。例如,一个可扩展的 Web 应用程序可以很好地与一个或多个用户一起工作,并且可以优雅地处理流量的高峰和低谷。

调整应用程序消耗的资源的灵活性是迁移到云的关键业务驱动力。通过适当的设计,您可以通过移除未充分利用的资源来降低成本,而不会影响性能或用户体验。通过添加更多资源,您同样可以在高流量期间保持良好的用户体验。这样,您的应用程序可以只消耗满足需求所需的资源。

Google Cloud 提供的产品和功能可帮助您构建可扩展的高效应用:

  • Compute Engine 虚拟机和 Google Kubernetes Engine (GKE) 集群与自动扩缩器集成,可让您根据定义的指标增加或缩减资源消耗。
  • Google Cloud 的无服务器平台提供托管计算、数据库和其他服务,可从零请求量快速扩展到高请求量,您只需为使用量付费。
  • BigQuery、Cloud Spanner 和 Cloud Bigtable 等数据库产品可以跨海量数据提供一致的性能。
  • Cloud Monitoring 提供跨应用和基础架构的指标,帮助您做出以数据为依据的扩展决策。

弹性:设计以承受失败


弹性应用程序是在系统组件出现故障的情况下仍能继续运行的应用程序。弹性需要在架构的各个级别进行规划。它会影响您布局基础架构和网络的方式以及设计应用程序和数据存储的方式。复原力也延伸到人和文化。

构建和运行弹性应用程序很困难。对于可能包含多层基础架构、网络和服务的分布式应用程序尤其如此。错误和中断时有发生,提高应用程序的弹性是一个持续的过程。通过仔细规划,您可以提高应用程序抵御故障的能力。通过适当的流程和组织文化,您还可以从失败中吸取教训,以进一步提高应用程序的弹性。

Google Cloud 提供工具和服务来帮助您构建高度可用且具有弹性的应用:

  • Google Cloud 服务可在全球各地的区域和地区使用,使您能够部署您的应用以最好地满足您的可用性目标。
  • Compute Engine 实例组和 GKE 集群可以跨区域中的可用地区分布和管理。
  • Compute Engine 区域永久性磁盘在区域中跨地区同步复制。
  • Google Cloud 提供了一系列负载平衡选项来管理您的应用流量,包括可以将流量引导到离您的用户最近的健康区域的全局负载平衡。
  • Google Cloud 的无服务器平台包括提供内置冗余和负载平衡的托管计算和数据库产品。
  • Google Cloud 通过原生工具和与流行开源技术的集成来支持 CI/CD,以帮助自动构建和部署您的应用。
  • Cloud Monitoring 提供跨应用和基础架构的指标,帮助您就应用的性能和运行状况做出以数据为依据的决策。


驱动因素和制约因素


提高应用程序的可扩展性和弹性有不同的要求和动机。也可能存在限制您实现可扩展性和弹性目标的能力的限制。这些要求和约束的相对重要性取决于应用程序的类型、用户的个人资料以及组织的规模和成熟度。

驱动力


为了帮助您优先考虑您的需求,请考虑来自组织不同部分的驱动因素。

业务驱动力


业务方面的常见驱动因素包括:

  • 优化成本和资源消耗。
  • 最大限度地减少应用程序停机时间。
  • 确保在高使用率期间能够满足用户需求。
  • 提高服务质量和可用性。
  • 确保在任何中断期间保持用户体验和信任。
  • 提高灵活性和敏捷性以应对不断变化的市场需求。

发展驱动力


开发方面的常见驱动因素包括:

  • 最大限度地减少调查故障所花费的时间。
  • 增加花在开发新功能上的时间。
  • 通过自动化最大限度地减少重复劳动。
  • 使用最新的行业模式和实践构建应用程序。

运营驱动力


从运营方面考虑的要求包括:

  • 减少需要人工干预的故障频率。
  • 增加从故障中自动恢复的能力。
  • 通过自动化最大限度地减少重复劳动。
  • 将任何特定组件故障的影响降至最低。

约束


约束可能会限制您提高应用程序的可扩展性和弹性的能力。确保您的设计决策不会引入或促成这些约束:

  • 对难以扩展的硬件或软件的依赖。
  • 对在高可用性配置中难以操作的硬件或软件的依赖。
  • 应用程序之间的依赖关系。
  • 许可限制。
  • 您的开发和运营团队缺乏技能或经验。
  • 组织对自动化的抵制。

模式和实践


本文档的其余部分定义了模式和实践,以帮助您构建弹性和可扩展的应用程序。这些模式涉及应用程序生命周期的所有部分,包括基础架构设计、应用程序架构、存储选择、部署流程和组织文化。

模式中的三个主题很明显:

  • 自动化。构建可扩展且有弹性的应用程序需要自动化。自动化您的基础架构配置、测试和应用程序部署可提高一致性和速度,并最大限度地减少人为错误。
  • 松耦合。将您的系统视为松散耦合的独立组件的集合,可以提供灵活性和弹性。独立性涵盖了您如何物理分配您的资源以及您如何构建您的应用程序和设计您的存储。
  • 数据驱动设计。收集指标以了解您的应用程序的行为至关重要。关于何时扩展您的应用程序或特定服务是否不健康的决定需要基于数据。指标和日志应该是核心功能。

自动化您的基础架构配置


通过自动化创建不可变的基础架构,以提高环境的一致性并提高部署的成功率。

将您的基础架构视为代码


基础架构即代码 (IaC) 是一种鼓励您以处理应用程序代码的方式处理基础架构供应和配置的技术。您的供应和配置逻辑存储在源代码控制中,因此可以发现并且可以进行版本控制和审核。因为它位于代码存储库中,所以您可以利用持续集成和持续部署 (CI/CD) 管道,从而可以自动测试和部署对配置的任何更改。

通过从基础架构配置中删除手动步骤,IaC 可以最大限度地减少人为错误并提高应用程序和环境的一致性和可重复性。通过这种方式,采用 IaC 可以提高应用程序的弹性。

Cloud Deployment Manager 可让您使用灵活的模板自动创建和管理 Google Cloud 资源。或者,Config Connector 允许您使用 Kubernetes 技术和工作流来管理您的资源。 Google Cloud 还内置了对流行的第三方 IaC 工具的支持,包括 Terraform、Chef 和 Puppet。

创建不可变的基础设施


不可变基础设施是一种建立在基础设施即代码优势之上的哲学。不可变的基础架构要求资源在部署后永远不会被修改。如果需要更新虚拟机、Kubernetes 集群或防火墙规则,您可以更新源存储库中资源的配置。测试并验证更改后,您可以使用新配置完全重新部署资源。换句话说,不是调整资源,而是重新创建它们。

创建不可变的基础架构会导致更可预测的部署和回滚。它还缓解了可变基础架构中常见的问题,例如配置漂移和雪花服务器。通过这种方式,采用不可变的基础架构可以进一步提高环境的一致性和可靠性。

高可用性设计


可用性是衡量服务可用时间的比例。可用性通常用作整体服务运行状况的关键指标。高可用性架构旨在最大限度地提高服务可用性,通常通过冗余部署组件。简单来说,实现高可用性通常涉及分配计算资源、负载平衡和复制数据。

物理分配资源


Google Cloud 服务可在全球各地使用。这些位置被划分为区域和区域。您在这些区域和专区部署应用程序的方式会影响应用程序的可用性、延迟和其他属性。如需了解详情,请参阅 Compute Engine 区域选择的最佳做法。

冗余是系统组件的复制,以提高该系统的整体可用性。在 Google Cloud 中,冗余通常是通过将您的应用或服务部署到多个区域甚至多个区域来实现的。如果一个服务存在于多个专区或地区,它可以更好地承受特定专区或地区的服务中断。尽管 Google Cloud 尽一切努力防止此类中断,但某些事件是不可预测的,最好做好准备。

借助 Compute Engine 托管实例组,您可以将虚拟机实例分布在一个区域中的多个地区,并将这些实例作为一个逻辑单元进行管理。 Google Cloud 还提供区域永久性磁盘,以自动将您的数据复制到一个区域中的两个地区。

同样,您可以通过创建区域集群来提高部署在 GKE 上的应用的可用性和弹性。区域集群将 GKE 控制平面组件、节点和 Pod 分布在一个区域内的多个区域中。由于您的控制平面组件是分布式的,因此即使在涉及一个或多个(但不是全部)区域的中断期间,您也可以继续访问集群的控制平面。

支持托管服务


您可以使用托管服务将应用程序堆栈的一部分作为服务来使用,而不是独立安装、支持和操作应用程序堆栈的所有部分。例如,您可以使用 Cloud SQL 提供的 MySQL 数据库,而不是在虚拟机 (VM) 上安装和管理 MySQL 数据库。然后,您可以获得可用性服务水平协议 (SLA),并可以依靠 GCP 来管理数据复制、备份和底层基础架构。通过使用托管服务,您可以减少管理基础架构的时间,而将更多时间用于提高应用程序的可靠性。

许多 Google Cloud 托管计算、数据库和存储服务都提供内置冗余,这可以帮助您实现可用性目标。其中许多服务提供区域模型,这意味着运行您的应用程序的基础设施位于特定区域并由 Google 管理,以便在该区域内的所有区域中冗余可用。如果某个区域不可用,您的应用程序或数据会自动从该区域的另一个区域提供。

某些数据库和存储服务还提供多区域可用性,这意味着运行您的应用程序的基础架构位于多个区域。多区域服务可以承受整个区域的丢失,但通常以更高的延迟为代价。

每一层的负载均衡


负载平衡允许您在资源组之间分配流量。当您分配流量时,您有助于确保单个资源不会在其他资源闲置时变得超载。大多数负载均衡器还提供健康检查功能,以帮助确保流量不会路由到不健康或不可用的资源。

Google Cloud 提供了多种负载平衡选择。如果您的应用在 Compute Engine 或 GKE 上运行,您可以根据流量的类型、来源和其他方面选择最合适的负载平衡器类型。有关更多信息,请参阅负载平衡概述和 GKE 网络概述。

或者,某些 Google Cloud 托管服务(例如 App Engine 和 Cloud Run)会自动对流量进行负载平衡。

通常的做法是对从外部来源(例如来自 Web 或移动客户端)接收到的请求进行负载平衡。但是,在应用程序的不同服务或层之间使用负载平衡器也可以提高弹性和灵活性。为此,Google Cloud 提供了内部第 4 层和第 7 层负载平衡。

下图显示了一个外部负载均衡器,它在两个区域 us-central1 和 asia-east1 之间分配全球流量。它还显示了将流量从 Web 层分配到每个区域内的内部层的内部负载平衡。

scalability

监控您的基础架构和应用程序


在决定如何提高应用程序的弹性和可扩展性之前,您需要了解其行为。访问有关应用程序性能和运行状况的一组全面的相关指标和时间序列可以帮助您在潜在问题导致中断之前发现它们。如果确实发生了中断,它们还可以帮助您诊断和解决中断。 Google SRE 书中的监控分布式系统一章很好地概述了一些监控方法。

除了提供对应用程序运行状况的洞察之外,指标还可用于控制服务的自动缩放行为。

Cloud Monitoring 是 Google Cloud 的集成监控工具。 Cloud Monitoring 提取事件、指标和元数据,并通过仪表板和警报提供见解。大多数 Google Cloud 服务会自动将指标发送到 Cloud Monitoring,而且 Google Cloud 还支持许多第三方来源。 Cloud Monitoring 还可以用作流行的开源监控工具的后端,提供一个“单一窗格”来观察您的应用。

各级监控


收集架构中不同级别或层级的指标可提供应用程序运行状况和行为的整体图景。

基础设施监控


基础设施级别的监控为您的应用程序提供基线运行状况和性能。这种监控方法可以捕获 CPU 负载、内存使用情况和写入磁盘的字节数等信息。这些指标可以指示机器过载或未按预期运行。

除了自动收集的指标之外,Cloud Monitoring 还提供了一个代理,可以安装该代理以从 Compute Engine 虚拟机(包括在这些机器上运行的第三方应用)收集更详细的信息。

应用监控


我们建议您捕获应用级指标。例如,您可能想要测量执行特定查询需要多长时间,或者执行相关的服务调用序列需要多长时间。您自己定义这些应用级指标。它们捕获内置 Stackdriver Monitoring 指标无法捕获的信息。应用程序级别的指标可以捕获更紧密地反映关键工作流的聚合条件,并且它们可以揭示低级别基础设施指标无法揭示的问题。

我们还建议使用 OpenCensus 来捕获您的应用级指标。 OpenCensus 是开源的,提供灵活的 API,并且可以配置为将指标导出到 Cloud Monitoring 后端。

服务监控


对于分布式和微服务驱动的应用程序,监控应用程序中不同服务和组件之间的交互非常重要。这些指标可以帮助您诊断问题,例如错误数量增加或服务之间的延迟。

Istio 是一个开源工具,可提供对微服务网络的洞察和操作控制。 Istio 为所有服务通信生成详细的遥测数据,并且可以将其配置为将指标发送到 Cloud Monitoring。

端到端监控


端到端监控,也称为黑盒监控,以用户看到的方式测试外部可见行为。这种类型的监控检查用户是否能够在您定义的阈值内完成关键操作。这种粗粒度监控可以发现细粒度监控可能无法发现的错误或延迟,并揭示用户感知的可用性。

暴露您的应用程序的健康状况


高度可用的系统必须有某种方法来确定系统的哪些部分是健康的并且运行正常。如果某些资源看起来不健康,系统可以将请求发送到其他地方。通常,健康检查涉及从端点提取数据以确定服务的状态或健康状况。

健康检查是负载均衡器的主要职责。当您创建与一组虚拟机实例关联的负载均衡器时,您还定义了运行状况检查。运行状况检查定义负载均衡器如何与虚拟机通信以评估特定实例是否应继续接收流量。负载均衡器健康检查也可用于自动修复实例组,以便重新创建不健康的机器。如果您在 GKE 上运行并通过入口资源对外部流量进行负载平衡,GKE 会自动为负载平衡器创建适当的运行状况检查。

Kubernetes 内置了对 liveness 和 readiness 探针的支持。这些探针帮助 Kubernetes 编排器决定如何管理集群中的 Pod 和请求。如果您的应用程序部署在 Kubernetes 上,最好通过适当的端点将应用程序的运行状况暴露给这些探测器。

建立关键指标


监控和健康检查为您提供有关应用行为和状态的指标。下一步是分析这些指标,以确定哪些指标最具描述性或影响力。关键指标会有所不同,具体取决于应用程序部署的平台以及应用程序正在执行的工作。

您不可能只找到一个指标来指示是否扩展您的应用程序,或者某个特定服务是否不健康。通常它是多种因素的组合,它们共同表明了一组特定的条件。借助 Stackdriver Monitoring,您可以创建自定义指标来帮助捕捉这些情况。谷歌 SRE 书提倡监控面向用户的系统的四个黄金信号:延迟、流量、错误和饱和度。

还要考虑您对异常值的容忍度。使用平均值或中值来衡量健康或绩效可能不是最佳选择,因为这些衡量标准可以隐藏广泛的不平衡。因此,考虑度量分布很重要;第 99 个百分位可能比平均值提供更多信息。

定义服务水平目标 (SLO)


您可以使用监控系统收集的指标来定义服务级别目标 (SLO)。 SLO 为您的服务指定性能或可靠性的目标级别。 SLO 是 SRE 实践的关键支柱,在 SRE 手册的服务水平目标章节以及 SRE 工作手册的实施 SLO 章节中进行了详细描述。

您可以使用服务监控根据 Stackdriver Monitoring 中的指标定义 SLO。您可以针对 SLO 创建警报策略,让您知道您是否有违反 SLO 的危险。

存储指标


监控系统中的指标在短期内有助于实时健康检查或调查最近的问题。 Cloud Monitoring 会将您的指标保留数周,以最好地满足这些用例。

但是,存储监控指标以进行长期分析也很有价值。访问历史记录可以帮助您采用数据驱动的方法来优化您的应用程序架构。您可以使用在中断期间和之后收集的数据来识别应用程序中的瓶颈和相互依赖关系。您还可以使用这些数据来帮助创建和验证有意义的测试。

历史数据还可以帮助验证您的应用是否在关键时期支持业务目标。例如,这些数据可以帮助您分析您的应用程序在过去几个季度甚至几年的高流量促销活动中如何扩展。

如需详细了解如何导出和存储指标,请参阅 Stackdriver Monitoring 指标导出解决方案。

确定缩放配置文件


您希望您的应用程序在不过度配置资源的情况下满足其用户体验和性能目标。

下图显示了应用程序扩展配置文件的简化表示。该应用程序维护资源的基线水平,并使用自动缩放来响应需求变化。

auto scaling

平衡成本和用户体验


决定是否扩展您的应用程序从根本上说是平衡成本与用户体验。确定您可接受的最低性能水平,以及可能在哪里设置上限。这些阈值因应用程序而异,也可能在单个应用程序内的不同组件或服务中有所不同。

例如,面向消费者的 Web 或移动应用程序可能具有严格的延迟目标。研究表明,即使是很小的延迟也会对用户对您的应用的看法产生负面影响,从而导致转化率降低和注册量减少。因此,确保您的应用具有足够的服务能力以快速响应用户请求非常重要。在这种情况下,运行更多 Web 服务器的更高成本可能是合理的。

对于非业务关键型内部应用程序的成本性能比可能会有所不同,因为用户可能更能容忍小的延迟。因此,您的扩展配置文件可能不那么激进。在这种情况下,保持低成本可能比优化用户体验更重要。

设置基线资源


扩展配置文件的另一个关键组成部分是确定适当的最小资源集。

Compute Engine 虚拟机或 GKE 集群通常需要时间来扩展,因为需要创建和初始化新节点。因此,即使没有流量,也可能需要维护最少的资源集。同样,基线资源的范围受应用程序类型和流量配置文件的影响。

相反,App Engine、Cloud Functions 和 Cloud Run 等无服务器技术旨在扩展至零,并且即使在冷启动的情况下也能快速启动和扩展。根据应用程序的类型和流量配置文件,这些技术可以为您的应用程序的某些部分提供效率。

配置自动缩放


自动缩放可帮助您自动缩放应用消耗的计算资源。通常,当超出某些指标或满足条件时会发生自动缩放。例如,如果对 Web 层的请求延迟开始超过某个值,您可能希望自动添加更多机器以增加服务容量。

许多 Google Cloud 计算产品都具有自动扩缩功能。 Cloud Run、Cloud Functions 和 App Engine 等无服务器托管服务旨在快速扩展。这些服务通常提供配置选项来限制或影响自动缩放行为,但通常,大部分自动缩放行为对操作员是隐藏的。

Compute Engine 和 GKE 提供了更多选项来控制扩展行为。借助 Compute Engine,您可以根据各种输入进行扩展,包括 Cloud Monitoring 自定义指标和负载平衡器服务容量。您可以设置缩放行为的最小和最大限制,并且可以定义具有多个信号的自动缩放策略来处理不同的场景。与 GKE 一样,您可以配置集群自动扩缩器以根据工作负载或 pod 指标或集群外部指标添加或删除节点。

我们建议您根据关键应用指标、成本配置文件以及定义的最低所需资源级别配置自动缩放行为。

最小化启动时间


为了使扩展有效,它必须足够快地发生以处理不断增加的负载。在添加计算或服务容量时尤其如此。

使用预烘焙的镜像


如果您的应用在 Compute Engine 虚拟机上运行,​​您可能需要安装软件并配置实例以运行您的应用。虽然您可以使用启动脚本来配置新实例,但更有效的方法是创建自定义映像。自定义映像是您使用特定于应用程序的软件和配置设置的启动磁盘。

有关管理映像的更多信息,请参阅映像管理最佳实践文章。

创建映像后,您可以定义实例模板。实例模板结合了启动磁盘映像、机器类型和其他实例属性。然后,您可以使用实例模板创建单个 VM 实例或托管实例组。实例模板是保存 VM 实例配置的便捷方式,以便您以后可以使用它来创建相同的新 VM 实例。

虽然创建自定义映像和实例模板可以提高您的部署速度,但也可能会增加维护成本,因为映像可能需要更频繁地更新。有关更多信息,请参阅平衡映像配置和部署速度文档。

容器化您的应用


构建自定义 VM 实例的另一种方法是将您的应用程序容器化。容器是一个轻量级的、独立的、可执行的软件包,包括运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。这些特性使容器化应用程序比虚拟机更便携、更易于部署和更易于大规模维护。容器通常也可以快速启动,这使得它们适用于可扩展和有弹性的应用程序。

Google Cloud 提供了多种服务来运行您的应用容器。 Cloud Run 提供了一个无服务器的托管计算平台来托管您的无状态容器。 App Engine 柔性环境将您的容器托管在托管平台即服务 (PaaS) 中。 GKE 提供托管 Kubernetes 环境来托管和编排您的容器化应用程序。当您需要完全控制容器环境时,您还可以在 Compute Engine 上运行应用容器。

优化您的应用程序以实现快速启动


除了确保您的基础架构和应用程序可以尽可能高效地部署之外,确保您的应用程序快速上线也很重要。

适合您的应用的优化因应用的特性和执行平台而异。执行以下操作很重要:

  • 通过分析启动时调用的应用程序的关键部分来查找并消除瓶颈。
  • 通过实施延迟初始化(尤其是昂贵资源)等技术来减少初始启动时间。
  • 最小化可能需要在启动时加载的应用程序依赖项。


喜欢模块化架构


您可以通过选择使组件能够独立部署、管理和扩展的架构来提高应用程序的灵活性。这种模式还可以通过消除单点故障来提高弹性。

将您的应用分解为独立的服务


如果您将应用程序设计为一组松散耦合的独立服务,则可以提高应用程序的灵活性。如果你采用松耦合的设计,它可以让你的服务独立发布和部署。除了许多其他好处之外,这种方法还使这些服务能够使用不同的技术堆栈并由不同的团队管理。这种松散耦合的方法是微服务和 SOA 等架构模式的关键主题。

当您考虑如何围绕服务划定界限时,可用性和可扩展性要求是关键维度。例如,如果给定组件的可用性要求或扩展配置文件与您的其他组件不同,则它可能是独立服务的良好候选者。

有关更多信息,请参阅将单体应用程序迁移到微服务。

以无状态为目标


无状态应用程序或服务不保留任何本地持久数据或状态。无状态模型确保您可以独立于先前的请求处理每个请求或与服务的交互。该模型促进了可扩展性和可恢复性,因为这意味着服务可以增长、缩小或重新启动,而不会丢失处理任何正在进行的进程或请求所需的数据。当您使用自动扩缩器时,无状态尤其重要,因为托管服务的实例、节点或 Pod 可能会被意外创建和销毁。

您的所有服务可能都不可能是无状态的。在这种情况下,需要明确说明需要状态的服务。通过确保无状态服务和有状态服务的清晰分离,您可以确保无状态服务的轻松可扩展性,同时为有状态服务采用更深思熟虑的方法。

管理服务之间的通信


分布式微服务架构的一个挑战是管理服务之间的通信。随着服务网络的增长,服务的相互依赖性也可能会增长。您不希望一个服务的故障导致其他服务的故障,有时称为级联故障。

您可以通过采用断路器模式、指数退避和优雅降级等技术来帮助减少过载服务或故障服务的流量。这些模式通过给过载的服务一个恢复的机会,或者通过优雅地处理错误状态来增加你的应用程序的弹性。有关更多信息,请参阅 Google SRE 书中的解决级联故障章节。

使用服务网格可以帮助您管理分布式服务的流量。服务网格是将服务链接在一起的软件,有助于将业务逻辑与网络分离。服务网格通常提供弹性功能,例如请求重试、故障转移和断路器。

使用适当的数据库和存储技术


某些数据库和存储类型难以扩展并具有弹性。确保您的数据库选择不会限制您的应用程序的可用性和可扩展性。

评估您的数据库需求


将您的应用程序设计为一组独立服务的模式也扩展到您的数据库和存储。为应用程序的不同部分选择不同类型的存储可能是合适的,这会导致异构存储。

传统应用程序通常专门使用关系数据库运行。关系数据库提供有用的功能,例如事务、强一致性、参照完整性和跨表的复杂查询。这些功能使关系数据库成为许多常见应用程序功能的不错选择。但是,关系数据库也有一些限制。它们通常难以扩展,并且需要在高可用性配置中进行仔细管理。关系数据库可能不是满足所有数据库需求的最佳选择。

非关系型数据库,通常称为 NoSQL 数据库,采用不同的方法。尽管细节因产品而异,但 NoSQL 数据库通常会牺牲关系数据库的某些功能,以提高可用性和更容易的可扩展性。根据 CAP 定理,NoSQL 数据库通常选择可用性而不是一致性。

NoSQL 数据库是否合适通常归结为所需的一致性程度。如果您的特定服务的数据模型不需要 RDBMS 的所有功能,并且可以设计为最终一致,那么选择 NoSQL 数据库可能会提供更高的可用性和可扩展性。

除了一系列关系数据库和 NoSQL 数据库之外,Google Cloud 还提供 Cloud Spanner,这是一个高度一致、高度可用且全球分布式的数据库,支持 SQL。有关在 GCP 上选择适当数据库的信息,请参阅 GCP 数据库。

实现缓存


缓存的主要目的是通过减少访问底层较慢存储层的需要来提高数据检索性能。

缓存通过减少对基于磁盘的存储的依赖来支持改进的可扩展性。由于可以从内存中处理请求,因此减少了到存储层的请求延迟,通常允许您的服务处理更多请求。此外,缓存可以减少应用程序下游服务(尤其是数据库)的负载,从而允许与该下游服务交互的其他组件也可以更轻松地扩展或完全扩展。

缓存还可以通过支持优雅降级等技术来提高弹性。如果底层存储层过载或不可用,缓存可以继续处理请求。即使从缓存返回的数据可能不完整或不是最新的,这在某些情况下也是可以接受的。

Memorystore for Redis 提供由 Redis 内存数据存储提供支持的完全托管服务。 Memorystore for Redis 为频繁访问的数据提供低延迟访问和高吞吐量。它可以部署在提供跨区域复制和自动故障转移的高可用性配置中。

现代化您的开发流程和文化


DevOps 可以被视为广泛的流程、文化和工具集合,通过打破开发、运营和相关团队之间的孤岛,提高应用程序和功能的敏捷性并缩短上市时间。 DevOps 技术旨在提高软件的质量和可靠性。

DevOps 的详细讨论超出了本文的范围,但与提高应用程序的可靠性和弹性相关的一些关键方面将在以下部分中讨论。有关更多详细信息,请参阅 Google Cloud DevOps 页面。

可测试性设计


自动化测试是现代软件交付实践的关键组成部分。执行一组全面的单元、集成和系统测试的能力对于验证您的应用程序是否按预期运行以及是否可以进入部署周期的下一阶段至关重要。可测试性是您的应用程序的关键设计标准。

我们建议您在大部分测试中使用单元测试,因为它们执行速度快且通常易于维护。我们还建议您自动化更高级别的集成和系统测试。如果您采用基础架构即代码技术,这些测试将大大简化,因为可以按需创建专用的测试环境和资源,然后在测试完成后将其拆除。

随着测试覆盖的代码库百分比的增加,您可以减少不确定性以及每次代码更改可能导致的可靠性下降。足够的测试覆盖率意味着您可以在可靠性低于可接受的水平之前进行更多更改。

自动化测试是持续集成的一个组成部分。对每个代码提交执行一组强大的自动化测试可以提供有关更改的快速反馈,从而提高软件的质量和可靠性。谷歌云原生工具(如 Cloud Build)和第三方工具(如 Jenkins)可以帮助您实施持续集成。

自动化您的部署


持续集成和全面的测试自动化让您对软件的稳定性充满信心。当它们到位时,您的下一步就是自动部署您的应用程序。部署自动化的级别取决于组织的成熟度。

选择适当的部署策略对于最大程度地降低与部署新软件相关的风险至关重要。通过正确的策略,您可以逐渐增加新版本向更多受众的曝光,并在此过程中验证行为。如果出现问题,您还可以为回滚设置明确的规定。

有关自动化部署的示例,请参阅使用 Spinnaker 在 GKE 上自动化 Canary 分析。

采用 SRE 实践来处理失败


对于大规模运行的分布式应用程序,一个或多个组件出现某种程度的故障是很常见的。如果您采用本文档中介绍的模式,您的应用程序可以更好地处理由有缺陷的软件版本、虚拟机意外终止甚至影响整个区域的基础架构中断造成的中断。

但是,即使经过精心设计的应用程序,您也不可避免地会遇到需要人工干预的意外事件。如果您采用结构化流程来管理这些事件,您可以大大减少它们的影响并更快地解决它们。此外,如果您检查事件的原因和响应,您可以帮助保护您的应用免受未来类似事件的影响。

管理事件和执行无可指责的事后分析的强大流程是 SRE 的关键原则。尽管实施 Google SRE 的完整实践对您的组织来说可能不切实际,但如果您采用最起码的指导方针,您就可以提高应用的弹性。 SRE 书中的附录包含一些可以帮助您塑造流程的模板。

验证和审查您的架构


随着您的应用程序的发展,用户行为、流量配置文件甚至业务优先级都会发生变化。同样,您的应用程序所依赖的其他服务或基础设施也可以发展。因此,定期测试和验证应用程序的弹性和可扩展性非常重要。

测试你的应变能力


测试您的应用程序是否以您期望的方式响应故障至关重要。最重要的主题是避免失败的最好方法是引入失败并从中吸取教训。

模拟和引入故障很复杂。除了验证您的应用程序或服务的行为之外,您还必须确保生成预期的警报,并生成适当的指标。我们建议采用结构化方法,在这种方法中引入简单的故障,然后逐步升级。

例如,您可能会进行如下操作,在每个阶段验证和记录行为:

  • 引入间歇性故障。
  • 阻止访问服务的依赖项。
  • 阻止所有网络通信。
  • 终止主机。

有关详细信息,请参阅 Google Cloud Next 2019 中的破解您的系统以使其牢不可破的视频。

如果您使用像 Istio 这样的服务网格来管理您的应用程序服务,您可以在应用程序层注入故障而不是杀死 pod 或机器,或者您可以在 TCP 层注入损坏的数据包。您可以引入延迟来模拟网络延迟或过载的上游系统。您还可以引入中止,它模仿上游系统中的故障。

测试你的缩放行为


我们建议您使用自动化的非功能测试来验证您的应用程序是否按预期扩展。这种验证通常与性能或负载测试相结合。您可以使用 hey 等简单工具将负载发送到 Web 应用程序。有关显示如何针对 REST 端点进行负载测试的更详细示例,请参阅使用 Google Kubernetes Engine 进行分布式负载测试。

一种常见的方法是确保关键指标保持在不同负载的预期水平内。例如,如果您正在测试 Web 层的可伸缩性,您可能会针对大量用户请求测量平均请求延迟。同样,对于后端处理功能,您可以测量任务量突然增加时的平均任务处理时间。

此外,您希望您的测试能够衡量为处理测试负载而创建的资源数量是否在预期范围内。例如,您的测试可能会验证为处理某些后端任务而创建的 VM 数量不超过某个值。

测试边缘情况也很重要。当达到最大扩展限制时,您的应用或服务的行为是什么?如果您的服务正在缩小然后负载突然再次增加,会发生什么行为?有关这些主题的讨论,请参阅旺季生产准备的负载测试部分。

永远做架构


技术世界发展迅速,云计算尤其如此。新产品和功能频繁发布,新模式出现,用户和内部利益相关者的需求不断增长。

正如云原生架构博客文章所定义的原则,始终在寻找改进、简化和改进应用程序架构的方法。软件系统是有生命的东西,需要适应以反映您不断变化的优先事项。

原文:https://cloud.google.com/architecture/scalable-and-resilient-apps

本文:https://jiagoushi.pro/node/2158

本文地址
https://architect.pub/patterns-scalable-and-resilient-apps
SEO Title
Patterns for scalable and resilient apps