本文档介绍了一些用于创建具有弹性和可扩展性的应用程序的模式和实践,这是许多现代架构练习的两个基本目标。设计良好的应用程序会随着需求的增加和减少而上下扩展,并且具有足够的弹性以承受服务中断。构建和运行满足这些要求的应用程序需要仔细规划和设计。
可扩展性:调整容量以满足需求
可扩展性是衡量系统通过在系统中添加或删除资源来处理不同数量的工作的能力。例如,一个可扩展的 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 层分配到每个区域内的内部层的内部负载平衡。
监控您的基础架构和应用程序
在决定如何提高应用程序的弹性和可扩展性之前,您需要了解其行为。访问有关应用程序性能和运行状况的一组全面的相关指标和时间序列可以帮助您在潜在问题导致中断之前发现它们。如果确实发生了中断,它们还可以帮助您诊断和解决中断。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 指标导出解决方案。