本文档介绍了一些在构建应用时应遵循的模式和做法,这些应用具备可扩缩和弹性佳两种优点,这也是许多现代化架构实践的两个基本目标。一个精心设计的应用能够随着需求的增减而相应扩容和缩容,并具有足够的弹性以应对服务中断。要顺利构建和运营可满足这些要求的应用,您需要仔细规划和设计。
可伸缩性:调整容量以满足需求
可伸缩性衡量的是系统通过添加或移除资源来处理各种水平的工作量的能力。例如,可扩缩的 Web 应用无论面对的是一位用户还是大量用户,都能应付自如并能从容处理流量的峰谷起落。
灵活调整应用消耗的资源是将业务迁移到云端的一项关键推动因素。通过适当的设计,您可以在不影响性能或用户体验的情况下移除利用率低的资源,从而降低成本。同样,您可以在高流量时段通过添加更多资源来保持良好的用户体验。这样,您的应用就可以仅消耗满足需求所需的资源。
Google Cloud 提供的产品和功能可帮助您构建可扩缩的高效应用:
- Compute Engine 虚拟机和 Google Kubernetes Engine (GKE) 集群与自动扩缩器集成,让您可以根据您定义的指标来相应地增加或减少资源消耗量。
- Google Cloud 的无服务器平台提供代管式计算、数据库和其他服务,这些服务可以从零流量快速扩容到高流量,而您只需为所用资源付费。
- BigQuery、Spanner 和 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 还内置了对 Terraform、Chef 和 Puppet 等热门的第三方 IaC 工具的支持。
创建不可变基础架构
不可变基础架构是一种基于基础架构即代码的优势构建的理念。不可变基础架构要求资源在部署后便不得修改。如果需要更新虚拟机、Kubernetes 集群或防火墙规则,则可以更新源代码库中资源的相应配置。在测试并验证更改后,您可以使用新配置完全重新部署资源。换句话说,您不是在调整资源,而是在重新创建资源。
创建不可变基础架构可实现更容易预测的部署和回滚,还可缓解可变基础架构中的常见问题,例如配置偏移和雪花型服务器。这样,采用不可变基础架构就可以进一步提高环境的一致性和可靠性。
设计时将高可用性考虑在内
可用性用于衡量服务可用时间所占的比例。 可用性通常用作服务整体运行状况的关键指标。高可用性架构旨在最大限度地提高服务可用性,通常通过冗余部署组件来实现。简单来说,实现高可用性通常涉及计算资源的分配、负载均衡和数据复制。
物理分布资源
Google Cloud 服务可在全球多个位置提供。我们将这些位置分为区域和地区。在这些区域和地区部署应用的方式会影响应用的可用性、延迟时间和其他属性。如需了解详情,请参阅选择 Compute Engine 区域时的最佳做法。
冗余是为了提高系统的整体可用性而复制系统组件。在 Google Cloud 中,通常通过将应用或服务部署到多个地区甚至多个区域来实现冗余。如果某服务存在于多个地区或区域中,则它可以更好地应对特定地区或区域中的服务中断。虽然 Google Cloud 会不遗余力地防止此类中断,但某些事件无法预测,因此最好做好准备。
借助 Compute Engine 代管实例组,您可以跨一个区域中的多个地区分布虚拟机实例,并且可以将实例作为逻辑单元进行管理。Google Cloud 还提供了区域永久性磁盘,用于将数据自动复制到一个区域中的两个可用区。
同样,您可以通过创建地区级集群来提高在 GKE 上部署的应用的可用性和弹性。区域级集群在一个区域内的多个可用区之间分配 GKE 控制平面组件、节点和 Pod。由于您的控制平面组件是分布式组件,因此,即使在涉及一个或多个(但非全部)区域的中断期间,您也可以继续访问集群的控制平面。
支持代管式服务
您可为应用栈的某些部分使用代管式服务,而不是独立地安装、支持和运营应用栈的所有部分。例如,您可以使用 Cloud SQL 提供的 MySQL 数据库,而不是在虚拟机 (VM) 上安装和管理 MySQL 数据库。然后,您将获得可用性服务等级协议 (SLA),并且可以依赖 Google Cloud 来管理数据复制、备份和底层基础架构。通过使用代管式服务,您可以节省管理基础架构的时间,并将更多时间用于提高应用的可靠性。
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 虚拟机(包括在这些机器上运行的第三方应用)中收集更多详细信息。
应用监控
我们建议您捕获应用级别的指标。例如,您可能希望测量执行特定查询或执行相关服务调用序列所需的时间。您可以自行定义这些应用级别的指标。它们会捕获内置 Cloud Monitoring 指标无法捕获的信息。应用级别的指标可以捕获可更贴切地反映关键工作流的汇总条件,并且可以反映低级别的基础架构指标无法发现的问题。
我们还建议使用 OpenTelemetry 来捕获应用级别的指标。OpenTelemetry 为遥测数据提供了一个单一的开放标准。您可以使用 OpenTelemetry 从您的云优先应用和基础架构收集和导出数据。然后,您可以监控和分析导出的遥测数据。
服务监控
对于微服务驱动型分布式应用,请务必监控应用中不同服务和组件之间的交互。这些指标可帮助您诊断错误数增加或服务之间出现延迟等问题。
Istio 是一种开源工具,可为您的微服务网络提供数据洞见和运维控制手段。Istio 会为所有服务通信生成详细的遥测数据,并且可以配置为将指标发送到 Cloud Monitoring。
端到端监控
端对端监控也称为黑盒监控,用于测试用户看到的外部可见行为。此类监控检查用户是否能够在指定的阈值范围内完成重要操作。这种粗粒度监控可以发现更细粒度的监控可能无法发现的错误或延迟,并揭示用户感知到的可用性情况。
公开应用的运行状况
可用性高的系统必须能够通过某些方式来确定系统的哪些部分状况良好且运行正常。如果某些资源显示状况不佳,则系统可以将请求发送到其他资源。通常,健康检查涉及从端点拉取数据以确定服务的状态或健康状况。
健康检查是负载均衡器的主要职责。当创建与一组虚拟机实例相关联的负载均衡器时,还需要定义健康检查。健康检查定义了负载均衡器与虚拟机的通信方式,以评估特定实例是否应继续接收流量。负载均衡器健康检查还可用于自动修复实例组,以便重新创建健康状况不佳的机器。如果您在 GKE 上运行并对经由 Ingress 资源的外部流量进行负载均衡,则 GKE 会自动为负载均衡器创建相应的健康检查。
Kubernetes 内置了对活跃性和就绪性探测的支持。这些探测可帮助 Kubernetes 协调器决定如何管理集群内的 pod 和请求。如果您的应用部署在 Kubernetes 上,则最好通过相应端点向这些探测公开应用的运行状况。
建立关键指标
监控和健康检查可提供有关应用的行为和状态的指标。下一步是分析这些指标,以确定哪些指标最具描述性或最具影响力。根据部署应用的平台以及应用正在执行的作业,关键指标会有所不同。
您不太可能仅找到一个指示是否扩缩应用或特定服务的运行状况不佳的指标。通常,它是一系列因素共同指示一组特定的条件。借助 Cloud Monitoring,您可以创建自定义指标来帮助捕获这些条件。《Google SRE》一书提出了用于监控面向用户的系统的四个黄金信号:延迟时间、流量、错误和饱和度。
此外,还请考虑您对离群值的容忍度。使用平均值或中间值来衡量运行状况或性能可能不是最好的选择,因为这些衡量标准可能会隐藏大量的不平衡情况。因此,请务必考虑指标分布;第 99 百分位可能比平均值提供的信息更丰富。
定义服务等级目标 (SLO)
您可以使用监控系统收集的指标来定义服务等级目标 (SLO)。SLO 指定服务性能或可靠性的目标等级。SLO 是 SRE 做法的关键支柱,SRE 图书服务等级目标一章以及 SRE 手册实现 SLO 一章对 SLO 进行了详细介绍。
您可以使用服务监控根据 Cloud Monitoring 中的指标来定义 SLO。您可以创建 SLO 相关提醒政策,以便了解自己是否面临违反 SLO 的危险。
存储指标
监控系统中的指标在短期内有助于您进行实时健康检查或调查近期问题。Cloud Monitoring 会将您的指标保留几周,以尽量满足这些用例需求。
不过,存储监控指标以进行长期分析也同样具有价值。获取历史记录有助于您采用数据驱动型方法优化应用架构。您可以使用在中断期间和之后收集的数据来确定应用中的瓶颈和相互依赖关系。您还可以使用这些数据来帮助创建和验证有意义的测试。
历史数据还有助于验证您的应用在关键时段是否支持业务目标。例如,数据可以帮助您分析您的应用在过去几个季度甚至几年的高流量促销活动中的扩缩情况。
如需详细了解如何导出和存储指标,请参阅 Cloud Monitoring 指标导出解决方案。
确定扩缩配置文件
您希望自己的应用能够在不过度预配资源的情况下实现其用户体验和性能目标。
下图简略地展示了应用的扩缩配置文件。应用维持基准级别的资源,并使用自动扩缩功能来响应需求变化。
平衡费用和用户体验
决定是否扩缩应用从根本上来说就是平衡费用和用户体验。确定您可接受的最低性能水平,以及可能的性能上限。这些阈值因应用而异,也可能因单个应用内的不同组件或服务而异。
例如,面向消费者的 Web 应用或移动应用可能会有严格的延迟时间目标值。调查显示,即使是略微晚点也会让用户对应用的体验产生负面影响,从而降低转化率并减少注册量。因此,请务必确保您的应用具有足够的服务容量以快速响应用户请求。在这种情况下,运行更多 Web 服务器所产生的较高费用可能是合理的。
对于非业务关键型的内部应用,性价比可能会有所不同,因为用户对稍微晚点的容忍度可能更高。因此,您的扩缩配置文件可以更加保守。在这种情况下,保持低费用可能比优化用户体验更为重要。
设置基准资源
扩缩配置文件的另一个关键环节是确定适当的最小资源集。
Compute Engine 虚拟机或 GKE 集群通常需要一段时间才能进行纵向扩容,因为需要创建和初始化新节点。因此,即使没有流量,也可能需要维护最小的资源集。同样,基准资源的范围也会受应用类型和流量配置文件的影响。
相反,App Engine、Cloud Run 函数和 Cloud Run 等无服务器技术可扩缩至零,并且可以快速启动和扩缩,即使在冷启动的情况下也是如此。这些技术可提高应用某些部分的效率,具体取决于应用类型和流量配置文件。
配置自动扩缩
自动扩缩功能可帮助您自动扩缩应用所使用的计算资源。通常,当超出特定指标或满足条件时,会发生自动扩缩。例如,如果您的 Web 层级的请求延迟时间开始超过某个特定值,您可能需要自动添加更多机器以提高服务容量。
许多 Google Cloud 计算产品都具有自动扩缩功能。Cloud Run、Cloud Run 函数和 App Engine 等无服务器代管式服务均可进行快速扩缩。这些服务通常会提供配置选项来限制或影响自动扩缩行为,但自动扩缩器的很多行为对运维人员来说都是不可见的。
Compute Engine 和 GKE 提供了更多选项来控制扩缩行为。借助 Compute Engine,您可以根据各种输入(包括 Cloud Monitoring 自定义指标和负载均衡器服务容量)进行扩缩。您可以针对扩缩行为设置下限和上限,还可以定义具有多个信号的自动扩缩政策来处理不同的场景。与 GKE 一样,您可以将集群自动扩缩器配置为根据工作负载或 Pod 指标或根据集群外部指标添加或移除节点。
我们建议您根据重要应用指标、费用配置文件以及定义的最低所需资源级别来配置自动扩缩行为。
最大限度地缩短启动时间
为有效进行扩缩,必须足够快速地处理不断增加的负载。在添加计算容量或服务容量时尤其如此。
使用预先专门构建的映像
如果您的应用在 Compute Engine 虚拟机上运行,则您可能需要安装软件并配置实例才能运行应用。虽然您可以使用启动脚本来配置新实例,但更高效的方法是创建自定义映像。自定义映像是您使用应用所需的软件和配置而专门设置的启动磁盘。
如需详细了解如何管理映像,请参阅映像管理最佳做法一文。
创建映像后,您可以定义实例模板。实例模板包含启动磁盘映像、机器类型和其他实例属性。然后,您可以使用实例模板创建单个虚拟机实例或代管实例组。实例模板是一种保存虚拟机实例配置的便捷方式,您日后可以用它来创建相同的新虚拟机实例。
虽然创建自定义映像和实例模板可以提高部署速度,但也会增加维护费用,因为可能需要更频繁地更新映像。如了解详情,请参阅在映像配置与部署速度之间达到均衡文档。
将应用容器化
构建自定义虚拟机实例的另一种方法是将应用容器化。container是一个独立的轻量级可执行软件包,其中包含运行应用所需的所有内容:代码、运行时环境、系统工具、系统库和设置。这些特性使容器化应用相较于虚拟机更易于移植、部署和大规模维护。通常,容器的启动速度也很快,因此适用于可扩缩且弹性佳的应用。
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 还提供了 Spanner,这是一个具有强一致性、高可用性且支持 SQL 的全球分布式数据库。如需了解如何在 Google Cloud 上选择合适的数据库,请参阅 Google Cloud 数据库。
实现缓存功能
缓存的主要用途是通过减少访问较缓慢的底层存储层的需求来提高数据检索性能。
缓存支持通过减少依赖磁盘式存储来提高可伸缩性。由于可以从内存传送请求,因此减少了向存储层发送请求的延迟时间,通常使服务能够处理更多的请求。此外,缓存还可减少应用下游服务的负载(尤其是数据库),从而与下游服务交互的其他组件也会进一步扩缩或完全扩缩。
缓存还可以通过支持优雅降级等技术来提高弹性。如果底层存储层过载或不可用,则缓存可以继续处理请求。虽然从缓存中返回的数据可能不完整或不是最新数据,但在某些情况下可能是可接受的。
Memorystore for Redis 提供全托管式服务,该服务由 Redis 内存数据存储区提供支持。Memorystore for Redis 为频繁访问的数据提供更低的访问延时和更高的吞吐量。它可以在提供跨地区复制和自动故障切换的高可用性配置中进行部署。
对开发流程和文化进行现代化改造
DevOps 可视为流程、文化和工具的广泛集合,通过打破开发、运营和相关团队之间的孤岛,提高应用和功能的敏捷性并缩短上市期。DevOps 技术旨在提高软件的质量和可靠性。
对 DevOps 的详细介绍不在本文的范围内,但以下部分介绍了与提高应用的可靠性和弹性相关的一些关键方面。如需了解详情,请参阅 Google Cloud DevOps 页面。
可测试性设计
自动化测试是现代软件交付实践的一个重要组成部分。能够执行一系列全面的单元、集成和系统测试对于验证应用的行为是否符合预期以及是否可以进入部署周期的下一阶段至关重要。可测试性是应用的重要设计标准。
我们建议您对大部分测试使用单元测试,因为单元测试执行速度快且通常易于维护。我们还建议自动执行较高级别的集成和系统测试。如果您采用基础设施即代码技术,这些测试将大大简化,因为您可以按需创建专用测试环境和资源,然后在测试完成后将其删除。
随着接受测试的代码库的百分比增加,您可以减少每次代码更改带来的不确定性和可靠性降低的可能性。足够的测试覆盖率意味着您可以在可靠性低于可接受的水平之前进行更多的更改。
自动化测试是持续集成不可或缺的组成部分。通过在每次提交代码时执行一组可靠的自动化测试,可快速提供针对更改的反馈,从而提高软件的质量和可靠性。Google Cloud 的原生工具(如 Cloud Build)和第三方工具(如 Jenkins)可帮助您实现持续集成。
实现部署自动化
持续集成和全面测试自动化让您对软件的稳定性充满信心。当它们落实到位后,下一步就是自动部署应用。根据组织的成熟度,部署的自动化程度会有所不同。
选择适当的部署策略对于最大限度地降低与部署新软件相关的风险至关重要。在部署了合适的策略后,您就可以逐步提高新版本在较大受众群体中的曝光率,并验证整个过程中的行为。如果出现问题,您还可以针对回滚设置明确的规定。
采用 SRE 做法处理故障
对于大规模运行的分布式应用,一个或多个组件出现一定程度的故障是很常见的。如果您采用本文档中介绍的模式,则您的应用可以更好地应对因软件版本存在缺陷、虚拟机意外终止,甚至影响整个地区的基础架构故障而导致的服务中断。
然而,即使是经过精心设计的应用,您也不可避免地会遇到需要人工干预的意外事件。如果您设置了结构化流程来管理这些事件,则可以大幅降低其影响并更快地解决这些问题。此外,如果您检查事件的起因以及对其的响应措施,则还可以帮助防止您的应用将来出现类似事件。
用于管理突发事件和执行无责备事后分析的可靠流程是 SRE 的关键原则。虽然实现《Google SRE》中的全部做法可能对您的组织不实用,但如果您采用哪怕是一组最低的准则,也可以提高应用的弹性。《SRE》中的附录包含一些模板,可帮助塑造您的流程。
验证和查看架构
随着应用的发展,用户行为、流量配置文件,甚至业务优先级都可能会发生变化。同样,您的应用所依赖的其他服务或基础架构也可能会不断演变。因此,定期测试和验证应用的弹性和可伸缩性就变得非常重要。
测试弹性
测试应用是否会按您预期的方式响应故障至关重要。 核心主题是,避免故障的最佳方式是引入故障并从中学习。
模拟和引入故障非常复杂。除了验证应用或服务的行为之外,您还必须确保生成预期的提醒以及相应的指标。我们建议您采用结构化方法来引入简单的故障,然后上报。
例如,您可以按以下步骤操作,验证和记录每个阶段的行为:
- 引入间歇性故障。
- 禁止访问服务的依赖项。
- 阻止所有网络通信。
- 终止主机。
如需了解详情,请参阅 Google Cloud Next 2019 中的现在破坏系统以换来将来的坚不可摧视频。
如果您使用 Istio 等服务网格来管理应用服务,则可以在应用层注入故障(而不是终止 Pod 或机器),或者在 TCP 层注入损坏的数据包。您可以引入延迟来模拟网络延迟或上游系统过载。您还可以引入中止,从而模拟上游系统故障。
测试扩缩行为
我们建议您使用非功能性自动化测试来验证您的应用是否按预期进行扩缩。此验证通常与性能或负载测试结合使用。您可以使用 hey 等简单工具将负载发送到 Web 应用。如需查看介绍如何针对 REST 端点进行负载测试的更详细示例,请参阅使用 Google Kubernetes Engine 执行分布式负载测试。
一种常用的方法是确保各种负载的关键指标保持在预期水平范围内。例如,如果您要测试 Web 层的可伸缩性,则可能会测量用户请求量峰值的平均请求延迟时间。同样,对于后端处理功能,您可能会测量任务量突然增加时的平均任务处理时间。
此外,您还希望测试衡量为处理测试负载而创建的资源数量是否在预期范围内。例如,您的测试可能会验证为处理某些后端任务而创建的虚拟机数量是否未超过特定值。
测试边缘用例也很重要。当达到扩缩上限时,您的应用或服务会出现什么行为?如果您的服务正在缩减,然后负载突然增加,会出现什么行为?
始终进行架构设计
技术领域的发展日新月异,云技术尤其如此。新产品和新功能频繁发布,新模式不断涌现,用户和内部利益相关方的需求不断增加。
根据云原生架构的原则博文的定义,我们始终要寻找方法来优化、简化和改进应用架构。软件系统不断演变,因此需要进行调整才能反映不断变化的优先级。
后续步骤
- 阅读云原生架构的原则博文。
- 如需详细了解 Google 生产环境的管理方式,请参阅《SRE》一书。
- 详细了解 Google Cloud 上的 DevOps 如何提高软件质量和可靠性。
- 探索有关 Google Cloud 的参考架构、图表和最佳做法。查看我们的 Cloud 架构中心。