可靠性工程

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

【可用性设计】 GCP 面向规模和高可用性的设计

Chinese, Simplified

Google Cloud 架构框架中的这份文档提供了用于构建服务的设计原则,以便它们能够容忍故障并根据客户需求进行扩展。当对服务的需求很高或发生维护事件时,可靠的服务会继续响应客户的请求。以下可靠性设计原则和最佳实践应该是您的系统架构和部署计划的一部分。

创建冗余以提高可用性


具有高可靠性需求的系统必须没有单点故障,并且它们的资源必须跨多个故障域进行复制。故障域是可以独立发生故障的资源池,例如 VM 实例、专区或区域。当您跨故障域进行复制时,您可以获得比单个实例更高的聚合级别的可用性。有关更多信息,请参阅区域和可用区。

作为可能成为系统架构一部分的冗余的具体示例,为了将 DNS 注册中的故障隔离到各个区域,请为同一网络上的实例使用区域 DNS 名称以相互访问。

设计具有故障转移功能的多区域架构以实现高可用性


通过将应用程序架构为使用分布在多个区域的资源池,并在区域之间进行数据复制、负载平衡和自动故障转移,使您的应用程序对区域故障具有弹性。运行应用程序堆栈每一层的区域副本,并消除架构中的所有跨区域依赖关系。

跨区域复制数据以进行灾难恢复


将数据复制或存档到远程区域,以便在发生区域中断或数据丢失时进行灾难恢复。使用复制时,恢复更快,因为远程区域的存储系统已经拥有几乎是最新的数据,除了可能由于复制延迟而丢失少量数据。当您使用定期存档而不是连续复制时,灾难恢复涉及从新区域中的备份或存档中恢复数据。与激活持续更新的数据库副本相比,此过程通常会导致更长的服务停机时间,并且由于连续备份操作之间的时间间隔,可能会导致更多的数据丢失。无论使用哪种方法,都必须在新区域中重新部署和启动整个应用程序堆栈,并且在这种情况下服务将不可用。

有关灾难恢复概念和技术的详细讨论,请参阅为云基础架构中断构建灾难恢复。

设计多区域架构以应对区域中断


如果您的服务即使在整个区域发生故障的极少数情况下也需要持续运行,请将其设计为使用分布在不同区域的计算资源池。运行应用程序堆栈每一层的区域副本。

在区域出现故障时使用跨区域的数据复制和自动故障转移。一些 Google Cloud 服务具有多区域变体,例如 BigQuery 和 Cloud Spanner。为了应对区域故障,请尽可能在您的设计中使用这些多区域服务。有关区域和服务可用性的更多信息,请参阅 Google Cloud 位置。

确保不存在跨区域依赖关系,以便区域级故障的影响范围仅限于该区域。

消除区域单点故障,例如在无法访问时可能导致全局中断的单区域主数据库。请注意,多区域架构通常成本更高,因此在采用此方法之前请考虑业务需求与成本。

有关跨故障域实施冗余的进一步指导,请参阅调查文件云应用程序的部署原型 (PDF)。

消除可扩展性瓶颈


识别不能超出单个 VM 或单个区域的资源限制的系统组件。一些应用程序垂直扩展,您可以在单个 VM 实例上添加更多 CPU 内核、内存或网络带宽来处理负载的增加。这些应用程序的可扩展性受到严格限制,您必须经常手动配置它们以应对增长。

如果可能,重新设计这些组件以水平扩展,例如跨 VM 或区域进行分片或分区。要处理流量或使用量的增长,您需要添加更多分片。使用可以自动添加的标准 VM 类型来处理每个分片负载的增加。有关更多信息,请参阅可扩展和弹性应用程序的模式。

如果您无法重新设计应用程序,您可以将由您管理的组件替换为完全托管的云服务,这些云服务旨在水平扩展而无需用户操作。

过载时优雅地降低服务水平


设计您的服务以容忍过载。服务应该检测过载并向用户返回质量较低的响应或部分丢弃流量,而不是在过载下完全失败。

例如,服务可以使用静态网页响应用户请求,并暂时禁用处理成本更高的动态行为。此行为在从 Compute Engine 到 Cloud Storage 的热故障转移模式中有详细说明。或者,该服务可以允许只读操作并暂时禁用数据更新。

当服务降级时,应通知操作员纠正错误情况。

防止和缓解流量高峰


不要跨客户端同步请求。在同一时刻发送流量的客户端过多会导致流量峰值,从而可能导致级联故障。

在服务器端实施峰值缓解策略,例如节流、排队、减载或断路、优雅降级和优先处理关键请求

客户端的缓解策略包括客户端限制和带抖动的指数退避。

清理和验证输入


为防止导致服务中断或安全漏洞的错误、随机或恶意输入,请清理和验证 API 和操作工具的输入参数。例如,Apigee 和 Google Cloud Armor 可以帮助防止注入攻击。

定期使用模糊测试,其中测试工具故意调用具有随机、空或太大输入的 API。在隔离的测试环境中进行这些测试。

操作工具应在更改推出之前自动验证配置更改,并在验证失败时拒绝更改。

以保留功能的方式进行故障保护


如果由于问题而出现故障,则系统组件应以允许整个系统继续运行的方式发生故障。这些问题可能是软件错误、错误的输入或配置、计划外的实例中断或人为错误。您的服务流程有助于确定您是否应该过度宽容或过于简单化,而不是过度限制。

考虑以下示例场景以及如何响应失败:

  • 对于配置错误或空配置的防火墙组件,通常最好在操作员修复错误时失败打开并允许未经授权的网络流量在短时间内通过。此行为使服务保持可用,而不是失败关闭并阻止 100% 的流量。该服务必须依赖于应用程序堆栈中更深层次的身份验证和授权检查,以在所有流量通过时保护敏感区域。
  • 但是,控制对用户数据的访问的权限服务器组件最好关闭失败并阻止所有访问。当配置损坏时,此行为会导致服务中断,但可以避免在打开失败时泄露机密用户数据的风险。

在这两种情况下,故障都应该引发高优先级警报,以便操作员可以修复错误情况。服务组件应该在失败打开方面犯错,除非它给业务带来极大风险。

将 API 调用和操作命令设计为可重试


API 和操作工具必须尽可能使调用重试安全。许多错误情况的一种自然方法是重试前一个操作,但您可能不知道第一次尝试是否成功。

您的系统架构应该使操作具有幂等性——如果您连续两次或多次对一个对象执行相同的操作,它应该产生与单次调用相同的结果。非幂等动作需要更复杂的代码来避免系统状态的损坏。

识别和管理服务依赖项


服务设计者和所有者必须维护对其他系统组件的完整依赖列表。服务设计还必须包括从依赖失败中恢复,或者如果完全恢复不可行,则优雅降级。考虑到系统使用的云服务的依赖关系和外部依赖关系,例如第三方服务 API,认识到每个系统依赖关系都有非零故障率。

当您设置可靠性目标时,请认识到服务的 SLO 在数学上受到其所有关键依赖项的 SLO 的约束。您不能比依赖项之一的最低 SLO 更可靠。有关详细信息,请参阅服务可用性的计算。

启动依赖


服务启动时的行为与其稳态行为不同。启动依赖项可能与稳态运行时依赖项有很大不同。

例如,在启动时,服务可能需要从它很少再次调用的用户元数据服务加载用户或帐户信息。当许多服务副本在崩溃或例行维护后重新启动时,副本会急剧增加启动依赖项的负载,尤其是当缓存为空且需要重新填充时。

在负载下测试服务启动,并相应地提供启动依赖项。考虑通过保存从关键启动依赖项中检索到的数据的副本来优雅降级的设计。此行为允许您的服务使用可能过时的数据重新启动,而不是在关键依赖项出现中断时无法启动。您的服务可以稍后在可行的情况下加载新数据以恢复正常操作。

在新环境中引导服务时,启动依赖项也很重要。使用分层架构设计您的应用程序堆栈,层之间没有循环依赖关系。循环依赖似乎是可以容忍的,因为它们不会阻止对单个应用程序的增量更改。但是,在灾难导致整个服务堆栈瘫痪后,循环依赖可能会导致难以或不可能重新启动。

最小化关键依赖


最小化您的服务的关键依赖项的数量,即其他组件的故障将不可避免地导致您的服务中断。为了使您的服务对它所依赖的其他组件的故障或缓慢具有更强的弹性,请考虑以下示例设计技术和原则,以将关键依赖项转换为非关键依赖项:

  • 增加关键依赖项中的冗余级别。添加更多副本可以降低整个组件不可用的可能性。
  • 对其他服务使用异步请求而不是阻塞响应,或者使用发布/订阅消息将请求与响应分离。
  • 缓存来自其他服务的响应以从短期不可用的依赖项中恢复。

为了减少服务中的故障或缓慢对依赖它的其他组件的危害,请考虑以下示例设计技术和原则:

  • 使用优先请求队列,并为用户等待响应的请求提供更高的优先级。
  • 从缓存中提供响应以减少延迟和负载。
  • 以保留功能的方式进行故障保护。
  • 当流量过载时优雅地降级。
  • 确保每次更改都可以回滚

如果没有明确定义的方法来撤消对服务的某些类型的更改,请更改服务的设计以支持回滚。定期测试回滚过程。每个组件或微服务的 API 都必须进行版本控制,并具有向后兼容性,这样前几代客户端才能随着 API 的发展继续正常工作。此设计原则对于允许逐步推出 API 更改以及在必要时快速回滚至关重要。

为移动应用程序实施回滚可能代价高昂。 Firebase Remote Config 是一项 Google Cloud 服务,可让功能回滚变得更容易。

您不能轻易回滚数据库架构更改,因此请分多个阶段执行它们。设计每个阶段以允许应用程序的最新版本和先前版本的安全模式读取和更新请求。如果最新版本出现问题,这种设计方法可以让您安全地回滚。

建议


要将架构框架中的指南应用于您自己的环境,请遵循以下建议:

  • 在客户端应用程序的错误重试逻辑中使用随机化实现指数退避。
  • 实施具有自动故障转移的多区域架构以实现高可用性。
  • 使用负载平衡在分片和区域之间分配用户请求。
  • 设计应用程序以在过载情况下优雅降级。 提供部分响应或提供有限的功能,而不是完全失败。
  • 为容量规划建立数据驱动的流程,并使用负载测试和流量预测来确定何时配置资源。
  • 建立灾难恢复程序并定期对其进行测试。

原文:https://cloud.google.com/architecture/framework/reliability/design-scal…

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

SEO Title
GCP Design for scale and high availability

【可靠性】建立可靠性文化

Chinese, Simplified

可靠性文化如何帮助团队构建更可靠的系统和流程。

当我们考虑可靠性时,我们通常会从系统的角度来考虑可靠性。现实情况是,可靠性始于人。通过鼓励站点可靠性工程师 (SRE)、事件响应人员、应用程序开发人员和其他团队成员主动考虑可靠性,我们可以更好地准备识别和修复故障模式。

在本节中,我们将解释什么是可靠性文化,如何培养和发展可靠性文化,以及它如何帮助提高我们的流程和系统的可靠性。


什么是可靠性文化?


可靠性文化是组织的每个成员都朝着最大化其服务、流程和人员可用性的共同目标而努力的文化。团队成员专注于提高其服务的可用性和性能,降低停机风险,并尽快响应事件以减少停机时间。

传统上,软件工程团队对待可靠性的方式与对待测试的方式相同:作为开发生命周期中的一个不同阶段。这导致可靠性成为质量保证 (QA) 和运营团队的唯一责任。随着系统变得越来越复杂和开发速度加快,可靠性不仅成为测试人员和运营团队之间的共同责任,而且成为构建应用程序的开发人员、领导这些团队的工程经理、解决客户痛点的产品经理,甚至是高管之间的共同责任负责预算和启动公司范围内的计划。所有这些团队都必须在使组织的服务更可靠的目标上保持一致,以便更好地为客户服务,我们将这种组织范围内的关注称为“可靠性文化”。

但是为什么我们需要一个专注于可靠性的整个文化呢?难道我们不能编写更多的自动化测试用例,或者将一个工具插入我们的 CI/CD 管道来为我们测试我们的应用程序吗?一方面,可靠性受到软件开发生命周期 (SDLC) 的所有阶段的影响,从设计一直到部署。在 SDLC 后期修复缺陷和故障模式的成本更高,特别是如果它们最终导致生产事故。

其次,现代应用程序和系统更加复杂,并且具有更多相互关联的部分。虽然传统测试擅长测试单个组件,但它不足以全面测试整个系统。提高可靠性意味着测试和加强这些复杂的相互作用,以防止一个组件的故障导致整个系统瘫痪。

最后,组织倾向于优先考虑其他计划而不是可靠性,例如缩短开发周期和快速发布新功能。这并不是因为可靠性不重要,而是因为它不是许多团队的首要任务。如果没有来自组织的强烈激励,提高可靠性的努力和举措就不太可能保持势头。更快的功能开发甚至可以通过使系统更不可靠来阻碍可靠性工作。

是什么推动了可靠性文化?


可靠性文化最终集中在一个目标上:提供最佳的客户体验。这种对客户的独特关注指导可靠性的所有其他方面,从开发更具弹性的应用程序和系统,到培训 SRE 以更有效地响应事件。当客户满意度和可靠性之间存在明显的相关性时,组织就会更有动力投入所需的时间、精力和预算,以使系统和流程更加可靠。它还将可靠性工作与公司的核心使命直接联系起来,进一步巩固了它作为一项重要实践的地位。

[“为什么我们需要可靠”的答案]只有一个词:信任!信任是我们能提供的最重要的东西。为了使我们的平台可行,我们的客户必须相信我们将可用,为了让我们赢得客户的信任,我们必须可靠。


如何发展和培养可靠性文化


建立可靠性文化所需的时间和精力与组织的规模成正比。即使在个人习惯于快速转向的初创公司中,确保每个人都在同一个目标上保持一致也是一项挑战。在建立可靠性文化时,我们需要考虑我们的目标。

从你的使命宣言开始


提高可靠性的主要目标是保持我们的系统和服务可用。频繁的中断会导致收入损失、客户信任度下降,以及用于响应事件而不是改进我们的产品或服务的工程时间。但是,尽管这是所有组织的一个重要目标,但它并不总是组织文化的一个引人注目的驱动力。那是什么?

这个问题的答案应该与组织的使命宣言密切相关。如果我们没有使命宣言或目标,我们应该从关注客户开始。我们如何提供最佳的客户体验,以及如何将其转化为我们组织的日常工作?

这个问题应该是整个组织的头等大事,尤其是在产品团队、工程团队、客户支持团队和执行团队中。每个团队都应该意识到他们的角色和职责如何为客户体验做出贡献。例如,如果工程师编写的代码优化不佳,这可能会导致性能下降和延迟增加,从而导致客户放弃产品。通过围绕客户构建可靠性,我们可以更轻松地开始思考不同团队如何影响可靠性目标。

为了让团队保持一致,我们应该经常重复我们的使命宣言。在会议、员工入职和规划新计划时突出显示它。如果对我们的可靠性目标或目标产生疑问,我们应该始终将它们与客户联系起来。

识别并响应回击


组织变革通常会遇到一些阻力。您可能会听到以下论点:可靠性测试太复杂,需要花费宝贵的时间进行功能开发,或者您已经忙于事件管理。虽然投资可靠性确实需要前期投资,但它带来的好处大大超过了成本。这些包括:

  • 减少影响客户的事件和中断,从而带来更好的客户体验。
  • 更少的待命事件和紧急页面,减轻工程师的压力。
  • 降低了高严重性错误进入生产的风险,使工程师能够专注于功能开发和其他增值任务。

在开发生命周期的早期提高可靠性


团队通常直到软件开发生命周期 (SDLC) 后期才考虑可靠性。传统上,工程团队将可靠性测试的责任留给了 QA。随着现代应用程序的复杂性和快速发展,这个过程不再是可扩展的或完全有效的。它不仅会为生产设置障碍并减慢发布周期,而且无法找到现代系统中存在的意外且独特的故障模式。

解决方案是向左移动,以便在整个 SDLC 中进行可靠性测试,而不仅仅是在最后。在规划新功能或新服务时,我们早在需求收集阶段就开始规划我们想要提供的客户体验。产品经理在开发开始之前设定对服务质量的期望,SRE 和应用程序开发人员定义指标来衡量和跟踪对这些要求的合规性,然后我们不断测试我们在整个开发过程中满足这些要求的能力。

通过及早优先考虑可靠性,对提高可靠性的关注自然会影响到参与开发过程的每个团队。这使我们能够尽早开始发现和解决缺陷,鼓励良好的开发实践,并降低问题进入生产的风险。这也有经济利益,因为稍后在 SDLC 中修复错误的成本更高。

采用支持可靠性文化的实践


文化是重要的一步,但我们也需要工具来帮助我们将文化付诸实践。在可靠性方面,我们需要一种方法来确保我们的响应团队准备好处理事件,我们的系统对技术故障具有弹性,并且我们对可靠性实践的关注能够为业务带来明确的投资回报 (ROI)。我们这样做的方式是使用混沌工程。

混沌工程是故意将故障注入系统,观察系统如何响应,使用这些观察来提高其可靠性,并验证我们的弹性机制是否有效的实践。虽然“系统”通常指的是技术系统(尤其是分布式系统),但我们也可以使用混沌工程来验证组织系统和流程。这包括事件管理和响应、灾难恢复和故障排除流程。

Chaos Engineering 可帮助团队主动测试可靠性威胁,并在开发过程的早期解决它们,从而降低事件或中断的风险。这包括测试事件响应计划、验证系统是否可以故障转移到冗余或备份系统,以及许多其他场景。


使用 GameDays 和 FireDrills 练习失败


采用可靠性文化的最大挑战之一是保持这种做法。可靠性不是一次就能实现的:它必须定期维护和验证。做到这一点的最佳方法是使用混沌工程定期主动地测试系统和流程。事实上,持续运行混沌实验的团队比从未进行过实验或运行临时实验的团队具有更高的可用性水平。

混沌工程如何帮助建立可靠性文化?答案是帮助团队测试他们对系统的假设,积极寻找提高可靠性的方法,并确保系统能够适应生产条件。这样做的一个常见策略是使用 GameDays,这是故意计划的事件,拥有应用程序或服务的工程师团队(以及其他利益相关者,如团队领导和产品经理)聚在一起对服务进行混沌实验.团队运行实验,观察服务以了解它如何响应,并利用他们的见解来提高服务的弹性。然后,他们将实验自动化,将其添加到他们的实验库中,然后连续运行这些实验以验证他们的系统是否保持弹性。

一个典型的 GameDay 运行时间为 2-4 小时,涉及以下团队成员:

  • 一位领导 GameDay 并决定何时运行或中止实验的成员(“所有者”)。
  • 执行实验的一名成员(“协调员”)。
  • 一名计划实验、定义假设(实验旨在测试什么)并记录结果的成员(“报告者”)。
  • 收集数据(通常来自监控或可观察性工具)并将实验效果与其数据相关联的一名或多名成员(“观察员”)。

为了帮助建立可靠性实践,请定期运行 GameDays。具有高可用性的团队倾向于每周、每月或每季度运行一次实验。一般来说,运行更频繁的 GameDays 可以帮助您更快地实现可靠性目标,因此请考虑安排每周或每两周的 GameDays。
一旦您的团队能够轻松运行计划内的事件,请考虑添加计划外事件。这些被称为 FireDrills。与 GameDay 一样,FireDrill 涉及使用混沌工程来模拟系统上的故障。不同之处在于响应 FireDrill 的团队不知道这是一次演习。这使他们以更现实的方式做出反应,就好像这是一个真实的事件,但保留了在必要时停止和回滚事件的能力。

FireDrills 可以有效地帮助团队:

  • 测量响应时间和平均解决时间 (MTTR)。
  • 确保运行手册是最新的。
  • 练习事件响应程序并建立肌肉记忆。
  • 测试监控仪表板、警报和待命/寻呼系统。

我们建议每周或每两周运行一次 FireDrills,但前提是您的团队已经练习过运行 GameDays。指定能够协调 FireDrill 的领导者,最好是了解被攻击系统的工程团队领导者。这可确保在发生意外情况或需要取消 FireDrill 时始终有人能够快速响应。

从错误中学习


事件会发生,这很好。没有一个系统是完美的。当出现问题时,采取纠正措施并尽快解决根本原因。然后,一旦您的系统正常运行,请对您的响应进行深入调查和评估(称为事后分析)。调查问题的原因、团队为解决问题所采取的步骤、有助于解决问题的指标和其他可观察性数据,以及团队为防止问题再次发生而采取的措施。

失败没关系:混乱即将发生,我们应该寻找失败只是为了学习。那些不舒服的地方是我们学到最多的地方。

事故对工程师来说是一段情绪紧张的时期,尤其是当他们觉得自己是造成事故的人时。进行事后分析时,不要专注于指责。相反,应首先关注使事件发生的过程。这被称为无可指责的事后分析。例如,如果团队成员将不良代码推到生产环境中,那么解决方案可能是更可控的部署管道、更彻底的自动化测试或更严格的同行评审。 “互相指责”只会阻止工程师分享他们的经验和见解,因为他们害怕受到惩罚或报复。

事件是学习和成长的机会。当您解决事件的根本原因时,请使用混沌工程来验证您的修复是否有效。自动化此过程以确保您的系统对故障保持弹性。不仅要在您自己的中断中练习,还要从其他团队和组织经历和记录的事件中练习。


总结一下……

 

  • 可靠性文化是组织的每个成员都在朝着提高组织可靠性的共同目标而努力的文化。
    • 可靠性始于客户。如果没有明确的、以客户为中心的使命宣言,可靠性计划就不太可能成功。
    • 构建可靠系统的责任由所有团队共同承担,而不仅仅是工程或 QA。
  • 文化确保可靠性不仅仅是一次性的举措,而是一个持续的过程和组织的一个组成部分。
    • GameDay 是留给团队运行一个或多个混沌实验并专注于技术成果的一段时间。
    • FireDrill 是一种训练团队的做法,让他们对故意制造的事件做出反应。
  • 通过采用工具来实践可靠性(例如混沌工程工具)并将它们集成到您的日常工作流程中,培养一种可靠性文化。
  • 始终愿意从您和其他人的事件中学习。

Additional resources

 

  • Twilio 如何建立可靠性文化
  • 让开发者成为开发者:抽象合规性 + 可靠性以加速 JPMC 的云部署
  • 在Charter Communications 扩大企业弹性文化
  • 创造混沌文化:混沌工程不仅仅是工具,更是文化
  • 如何建立高严重性事件管理程序
  • 使用我们的 Confluence 模板为您的组织轻松创建混沌工程 wiki
 

本文:https://jiagoushi.pro/creating-culture-reliability

SEO Title
Creating a culture of reliability

【可靠性工程】GCP 可靠性核心原则

Chinese, Simplified

Google Cloud Architecture Framework 中的这份文档解释了在云平台上运行可靠服务的一些核心原则。这些原则有助于您在阅读架构框架的其他部分时达成共识,这些部分向您展示了一些 Google Cloud 产品和功能如何支持可靠的服务。

关键术语


在架构框架可靠性类别中,使用了以下术语。这些术语提供了对如何运行可靠服务的关键理解。

服务水平指示器 (SLI)


服务水平指标 (SLI) 是对正在提供的服务水平的某些方面进行仔细定义的定量测量。它是一个指标,而不是一个目标。

服务水平目标 (SLO)


服务级别目标 (SLO) 指定服务可靠性的目标级别。 SLO 是 SLI 的目标值。当 SLI 等于或优于该值时,该服务被认为是“足够可靠”。由于 SLO 是制定有关可靠性的数据驱动决策的关键,因此它们是站点可靠性工程 (SRE) 实践的焦点。

错误预算


错误预算计算为 100% – SLO 在一段时间内。错误预算会告诉您,您的系统在特定时间窗口内是否比所需的可靠性更高或更低,以及在此期间允许停机多少分钟。

例如,如果您的可用性 SLO 为 99.9%,则 30 天期间的错误预算为 (1 - 0.999) ✕ 30 天 ✕ 24 小时 ✕ 60 分钟 = 43.2 分钟。每当系统不可用时,系统的错误预算就会被消耗或烧毁。使用前面的示例,如果系统在过去 30 天内有 10 分钟的停机时间,并且在 43.2 分钟的全部预算未使用的情况下开始了 30 天的周期,则剩余的错误预算将减少到 33.2 分钟。

我们建议在计算总错误预算和错误预算消耗率时使用 30 天的滚动窗口。

服务水平协议 (SLA)


服务水平协议 (SLA) 是与您的用户签订的明示或隐含合同,其中包括您遇到或错过合同中引用的 SLO 时的后果。

核心原则


Google 的可靠性方法基于以下核心原则。

可靠性是您的首要功能


新产品功能有时是您短期内的首要任务。但是,从长远来看,可靠性是您的首要产品功能,因为如果产品速度太慢或长时间不可用,您的用户可能会离开,从而使其他产品功能变得无关紧要。

可靠性由用户定义


对于面向用户的工作负载,衡量用户体验。用户必须对您的服务执行方式感到满意。例如,衡量用户请求的成功率,而不仅仅是 CPU 使用率等服务器指标。

对于批处理和流式工作负载,您可能需要衡量数据吞吐量的关键性能指标 (KPI),例如每个时间窗口扫描的行数,而不是服务器指标,例如磁盘使用情况。吞吐量 KPI 有助于确保按时完成用户所需的每日或季度报告。

100% 的可靠性是错误的目标


你的系统应该足够可靠,让用户满意,但又不能过于可靠,以至于投资不合理。定义设置所需可靠性阈值的 SLO,然后使用错误预算来管理适当的变化率。

仅当该产品或应用程序的 SLO 证明成本合理时,才将该框架中的设计和操作原则应用于产品。

可靠性与快速创新相辅相成


使用错误预算在系统稳定性和开发人员敏捷性之间取得平衡。以下指南可帮助您确定何时快速或慢速移动:

  • 当有足够的错误预算可用时,您可以快速创新并改进产品或添加产品功能。
  • 当错误预算减少时,放慢速度并专注于可靠性功能。


设计和操作原则


为了最大限度地提高系统可靠性,以下设计和操作原则适用。在架构框架可靠性类别的其余部分中详细讨论了这些原则中的每一个。

定义您的可靠性目标


架构框架的这一部分涵盖的最佳实践包括以下内容:

  • 选择适当的 SLI。
  • 根据用户体验设置 SLO。
  • 迭代改进 SLO。
  • 使用严格的内部 SLO。
  • 使用错误预算来管理开发速度。

有关详细信息,请参阅在架构框架可靠性类别中定义您的可靠性目标。

在您的基础架构和应用程序中构建可观察性


架构框架的这一部分涵盖了以下设计原则:

  • 检测您的代码以最大限度地提高可观察性。

有关更多信息,请参阅架构框架可靠性类别中的在基础架构和应用程序中构建可观察性。

为规模和高可用性而设计


架构框架的这一部分涵盖了以下设计原则:

  • 创建冗余以提高可用性。
  • 跨区域复制数据以进行灾难恢复。
  • 设计多区域架构以应对区域中断。
  • 消除可扩展性瓶颈。
  • 过载时优雅地降低服务级别。
  • 防止和缓解流量高峰。
  • 清理和验证输入。
  • 以保留系统功能的方式进行故障保护。
  • 将 API 调用和操作命令设计为可重试。
  • 识别和管理系统依赖项。
  • 最小化关键依赖。
  • 确保每次更改都可以回滚。

有关详细信息,请参阅架构框架可靠性类别中的规模和高可用性设计。

创建可靠的操作流程和工具


架构框架的这一部分涵盖了以下操作原则:

  • 为应用程序和服务选择好的名称。
  • 通过金丝雀测试程序实施渐进式部署。
  • 分散流量以进行定时促销和发布。
  • 自动化构建、测试和部署过程。
  • 防止操作员错误。
  • 测试故障恢复程序。
  • 进行灾难恢复测试。
  • 练习混沌工程。

有关详细信息,请参阅架构框架可靠性类别中的创建可靠的操作流程和工具。

建立有效的警报


架构框架的这一部分涵盖了以下操作原则:

  • 优化警报延迟。
  • 警惕症状,而不是原因。
  • 警惕异常值,而不是平均值。

有关详细信息,请参阅架构框架可靠性类别中的构建高效警报。

建立协作事件管理流程


架构框架的这一部分涵盖了以下操作原则:

  • 分配明确的服务所有权。
  • 通过精心调整的警报缩短检测时间 (TTD)。
  • 通过事件管理计划和培训缩短缓解时间 (TTM)。
  • 设计仪表板布局和内容以最小化 TTM。
  • 记录已知中断情况的诊断程序和缓解措施。
  • 使用无可指责的事后分析从中断中学习并防止再次发生。

有关详细信息,请参阅架构框架可靠性类别中的构建协作事件管理流程。

原文:https://cloud.google.com/architecture/framework/reliability/principles

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

SEO Title
GCP Reliability core principles

【可靠性工程】GCP 定义您的可靠性目标

Chinese, Simplified

Google Cloud 架构框架中的这份文档提供了最佳做法,用于定义适当的方法来衡量您的服务的客户体验,以便您可以运行可靠的服务。您将了解如何迭代您定义的服务级别目标 (SLO),并使用错误预算来了解如果发布其他更新,可靠性可能会受到影响。

选择合适的 SLI


选择适当的服务水平指标 (SLI) 以充分了解您的服务执行情况非常重要。例如,如果您的应用程序具有多租户架构,这是由多个独立客户使用的典型 SaaS 应用程序,请在每个租户级别捕获 SLI。如果您的 SLI 仅在全局聚合级别进行测量,您可能会错过应用程序中影响单个重要客户或少数客户的关键问题。相反,将您的应用程序设计为在每个用户请求中包含一个租户标识符,然后将该标识符传播到堆栈的每一层。此标识符允许您的监控系统在请求路径上的每一层或微服务的每个租户级别汇总统计信息。

您运行的服务类型还决定了要监控的 SLI,如以下示例所示。

服务系统


以下 SLI 在提供数据的系统中是典型的:

  • 可用性告诉您服务可用的时间比例。它通常根据格式良好的请求成功的比例来定义,例如 99%。
  • 延迟告诉您可以以多快的速度满足一定百分比的请求。它通常以第 50 位以外的百分位来定义,例如“300 毫秒时的第 99 个百分位”。
  • 质量告诉你某个反应有多好。质量的定义通常是特定于服务的,并表示对请求的响应内容与理想响应内容的差异程度。响应质量可以是二元的(好或坏)或以 0% 到 100% 的范围表示。


数据处理系统


以下 SLI 在处理数据的系统中是典型的:

  • 覆盖率告诉您已处理的数据比例,例如 99.9%。
  • 正确性告诉您被认为正确的输出数据的比例,例如 99.99%。
  • 新鲜度告诉您源数据或聚合输出数据的新鲜程度。通常,更新越近越好,例如 20 分钟。
  • 吞吐量告诉您正在处理多少数据,例如 500 MiB/秒甚至每秒 1000 个请求 (RPS)。


存储系统


以下 SLI 在存储数据的系统中是典型的:

  • 持久性告诉您写入系统的数据在未来被检索到的可能性有多大,例如 99.9999%。任何永久性数据丢失事件都会降低持久性指标。
  • 吞吐量和延迟也是存储系统的常见 SLI。

根据用户体验选择 SLI 并设置 SLO


本架构框架部分的核心原则之一是可靠性由用户定义。尽可能靠近用户测量可靠性指标,例如以下选项:

  • 如果可能,请检测移动或 Web 客户端。
    • 例如,使用 Firebase 性能监控来深入了解您的 iOS、Android 和 Web 应用程序的性能特征。
  • 如果这不可能,请检测负载平衡器。
    • 例如,将 Cloud Monitoring 用于外部 HTTP(S) 负载平衡器日志记录和监控。
  • 衡量服务器的可靠性应该是最后的选择。
    • 例如,使用 Stackdriver Monitoring 监控 Compute Engine 实例。

将您的 SLO 设置得足够高,以使几乎所有用户都对您的服务感到满意,而不是更高。由于网络连接或其他短暂的客户端问题,您的客户可能不会注意到应用程序中的短暂可靠性问题,从而允许您降低 SLO。

对于正常运行时间和其他重要指标,目标是低于 100% 但接近它。服务所有者应客观地评估使大多数用户满意的最低服务性能和可用性水平,而不仅仅是根据外部合同水平设定目标。

您更改的速率会影响系统的可靠性。但是,频繁进行小幅更改的能力可以帮助您更快、更优质地交付功能。根据客户体验调整的可实现的可靠性目标有助于定义客户可以容忍的最大变化速度和范围(功能速度)。

如果您无法衡量客户体验并围绕它定义目标,您可以运行竞争基准分析。如果没有可比的竞争,衡量客户体验,即使你还不能定义目标。例如,衡量系统可用性或对客户进行有意义且成功的交易的比率。您可以将此数据与业务指标或 KPI 相关联,例如零售订单量或客户支持电话和工单的数量及其严重性。在一段时间内,您可以使用此类关联练习来达到合理的客户满意度阈值。此阈值是您的 SLO。

有关如何选择正确的 SLI 和定义 SLO 的更多信息,请参阅定义 SLO。

迭代改进 SLO


SLO 不应一成不变。每季度或至少每年重新访问 SLO,并确认它们继续准确反映用户的幸福感并与服务中断密切相关。确保它们涵盖当前的业务需求和新的关键用户旅程。在这些定期审查之后,根据需要修改和增加您的 SLO。

使用严格的内部 SLO


拥有比外部 SLA 更严格的内部 SLO 是一种很好的做法。由于违反 SLA 往往需要签发财务信用或客户退款,因此您希望在问题产生财务影响之前解决问题。

我们建议您将这些更严格的内部 SLO 与无可指责的事后分析流程和事件审查一起使用。有关更多信息,请参阅架构中​​心可靠性类别中的构建协作事件管理流程。

使用错误预算来管理开发速度


错误预算会告诉您您的系统在某个时间窗口内是否比所需的可靠性更高或更低。错误预算按 100% 计算——一段时间内的 SLO,例如 30 天。

当您的错误预算中有剩余容量时,您可以继续快速启动改进或新功能。当错误预算接近于零时,冻结或减慢服务更改并投入工程资源以提高可靠性功能。

Google Cloud 的运营套件包括 SLO 监控,以最大程度地减少设置 SLO 和错误预算的工作量。操作套件包括一个图形用户界面,可帮助您手动配置 SLO,一个用于编程设置 SLO 的 API,以及用于跟踪错误预算消耗率的内置仪表板。有关详细信息,请参阅如何创建 SLO。

建议


要将架构框架中的指南应用到您自己的环境中,请遵循以下建议:

  • 定义和衡量以客户为中心的 SLI,例如服务的可用性或延迟。
  • 定义比外部 SLA 更严格的以客户为中心的错误预算。包括违规后果,例如生产冻结。
  • 设置延迟 SLI 以捕获异常值,例如第 90 或第 99 个百分位数,以检测最慢的响应。
  • 至少每年检查一次 SLO,并确认它们与用户满意度和服务中断密切相关。

原文:https://cloud.google.com/architecture/framework/reliability/define-goals

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

SEO Title
GCP Define your reliability goals

【可靠性工程】Microsoft 可靠性模式

Chinese, Simplified

可用性


可用性以正常运行时间的百分比来衡量,并定义了系统正常运行和工作的时间比例。 可用性受系统错误、基础设施问题、恶意攻击和系统负载的影响。 云应用程序通常为用户提供服务水平协议 (SLA),这意味着必须设计和实施应用程序以最大限度地提高可用性。

Pattern Summary
Deployment Stamps 部署应用程序组件的多个独立副本,包括数据存储
Geodes 将后端服务部署到一组地理节点中,每个节点都可以为任何区域的任何客户端请求提供服务。
Health Endpoint Monitoring 在外部工具可以通过暴露的端点定期访问的应用程序中实施功能检查。
Queue-Based Load Leveling 使用队列作为任务和它调用的服务之间的缓冲区,以平滑间歇性重负载。
Throttling 控制应用程序实例、单个租户或整个服务对资源的消耗。

为了缓解来自恶意分布式拒绝服务 (DDoS) 攻击的可用性风险,请实施本机 Azure DDoS 保护标准服务或第三方功能。

高可用性


Azure 基础架构由地理、区域和可用区组成,它们限制了故障的爆炸半径,从而限制了对客户应用程序和数据的潜在影响。 Azure 可用区构造旨在提供软件和网络解决方案,以防止数据中心故障并为我们的客户提供更高的高可用性 (HA)。 借助 HA 架构,可以在高弹性、低延迟和成本之间取得平衡。

Pattern Summary
Deployment Stamps 部署应用程序组件的多个独立副本,包括数据存储。
Geodes 将后端服务部署到一组地理节点中,每个节点都可以为任何区域的任何客户端请求提供服务。
Health Endpoint Monitoring 在外部工具可以通过暴露的端点定期访问的应用程序中实施功能检查。
Bulkhead 将应用程序的元素隔离到池中,以便如果一个失败,其他元素将继续运行。
Circuit Breaker 处理连接到远程服务或资源时可能需要不同时间才能修复的故障。

弹性


弹性是系统从疏忽和恶意故障中优雅地处理和恢复的能力。

云托管的性质,其中应用程序通常是多租户的、使用共享平台服务、竞争资源和带宽、通过 Internet 通信以及在商品硬件上运行,这意味着出现瞬时和更永久故障的可能性增加 . 互联网的连接性以及攻击的复杂性和数量的增加增加了安全中断的可能性。

检测故障并快速有效地恢复是保持弹性的必要条件。

Pattern Summary
Bulkhead 将应用程序的元素隔离到池中,以便在其中一个失败时,其他元素将继续运行。
Circuit Breaker 处理连接到远程服务或资源时可能需要花费可变时间来修复的故障。
Compensating Transaction 撤消由一系列步骤执行的工作,这些步骤共同定义了最终一致的操作。
Health Endpoint Monitoring 在外部工具可以定期通过公开端点访问的应用程序中实现功能检查。
Leader Election 通过选择一个实例作为负责管理其他实例的负责人,协调分布式应用程序中协作任务实例集合执行的操作。
Queue-Based Load Leveling 使用队列作为任务和它调用的服务之间的缓冲区,以平滑间歇性重载。
Retry 通过透明地重试以前失败的操作,使应用程序在尝试连接到服务或网络资源时能够处理预期的临时故障。
Scheduler Agent Supervisor 跨一组分布式服务和其他远程资源协调一组操作。

 

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

SEO Title
Microsoft Reliability patterns

【可靠性架构】可靠性架构第1部分:概念

Chinese, Simplified

可靠性

本故事的目标是提供可靠性的最佳实践来管理您的云环境。尽管它引用了AWS和Cloud,但这些原则同样适用于其他云提供商和内部环境。

本故事将分为三个部分。

  • 第1部分-描述各种术语和最佳实践的概念
  • 第2部分-云的弹性和可用性设计模式
  • 第3部分—实现特定SLA的高可用性体系结构

本故事集中在第1部分

AWS于2015年发布了良好架构框架,并描述了良好架构原则的五大支柱,即

  • 可靠性
  • 安全
  • 性能效率
  • 成本优化
  • 卓越运营

本故事侧重于可靠性支柱,提供了可靠性的要点,以供快速参考,并基于AWS白皮书和Microsoft云设计模式。

可靠性集中在以下方面

  • 能够从基础设施/服务故障中恢复
  • 快速获取需求资源以满足需求的能力
  • 缓解配置和瞬态网络问题

可用性

可用性=正常运行时间/总时间,表示为正常运行时间的百分比,例如99.99%。简而言之,以9的数量表示,例如99.999表示为五个9

作为快速参考,99%的可用性意味着每年3天15小时的停机时间99.999%意味着每年5分钟的停机时间。要计算特定值,请使用链接https://uptime.is/99.9或结账https://en.wikipedia.org/wiki/High_availability

如果存在相关性,则可用性是系统可用性和从属系统可用性的乘积。例如,如果系统A具有99.9%,系统B具有99.9%,并且A依赖于B,则聚合系统的可用性为99.9*99.9=99.8%

如果系统存在冗余,则正常运行时间计算为100减去组件故障率的乘积。例如,如果可用性为99.9,则故障率为0.1%,由此产生的可用性为100减去(0.1*0.1)=999.99%,这表明由于冗余而增加了可用性。

有时可能不知道依赖项的可用性。如果我们知道平均故障间隔时间(MTBF)和平均恢复时间(MTTR),那么可用性=MTBF/(MTBF+MTTR)。例如,MTBF为150天,MTTR为1小时,则可用性为99.97%。使用链接对此进行更深入的了解。

实现最高级别的可用性意味着部署/容量添加/回滚等方面的系统成本和复杂性更高。即使没有使用所有功能,也通常会为已建立的系统支付更高可用性的费用。必须考虑成本,小心制定正确的可用性目标。

弹性网络设计-关键指南

  • 在设计VPC和子网CIDR块时,考虑到所有对等可能性、本地重叠、Lambdas/ELB所需的IP数量等,考虑到未来的情况。
  • 为VPN连接和直连使用冗余
  • 利用AWS Shield、WAF、Route 53等AWS服务防止DDoS攻击

高可用性应用程序设计

为“五个9”或更高的HA进行设计需要极端的考虑。许多服务提供商和软件库的设计并不是为了提供这样的数量,这需要添加多个服务提供商,避免单点故障和定制开发,以及操作的极端自动化和彻底的故障测试。

应用程序必须处理的一些中断类型如下

  • 硬件故障
  • 部署失败
  • 增加的负载
  • 意外的输入错误
  • 凭据/证书过期
  • 依赖项失败
  • 电力等基础设施故障

所有这些故障都必须得到处理,恢复必须自动化。这意味着实现HA的工作不是微不足道的,并导致了可用性目标需求的细化。这可能是因为某些交易必须比其他交易更可靠,高峰时间、地理差异等。。

了解可用性需求

整个系统不需要设计为高可用性。例如,实时操作可能比批处理更重要,非高峰时间可能对可用性有容忍度,数据平面与控制平面,例如,现有EC2的健康状况和操作可能比能够启动新实例更重要,等等。

应用程序可用性设计

通过利用经验证的实践,可以显著提高应用程序可用性。以下原则指导HA的应用程序设计

  • 故障隔离区:通过利用AWS可用区和区域,可以将影响降低到特定区域。跨区域利用复制技术可降低数据丢失的风险
  • 冗余:避免单点故障是关键。构建对单个断层带故障具有弹性的软件非常重要
  • MicroServices:通过使用MicroServices架构构建,我们可以区分不同组件之间的可用性需求。架构中存在权衡,请查看https://martinfowler.com/articles/microservice-trade-offs.html
  • 面向恢复的计算:减少恢复影响时间至关重要。恢复程序基于影响而不是发生的问题类型。在某些情况下,如EC2,终止它并让ASG生成一个新实例可能比试图确定确切的问题并修复要好。定期测试恢复路径对于始终评估程序的有效性至关重要
  • 分布式系统最佳实践:分布式系统的一些最佳实践包括:节流(速率限制)、在返回故障之前重试一定次数、在特定条件下快速失败、确保处理一次的Idemptency令牌、保持服务始终以恒定工作预热、检查依赖性可用性的断路器、,静态稳定性,以确保系统在故障期间工作更少,而不是使系统进一步过载

可用性的操作注意事项

规划应用程序整个生命周期中使用的自动化或人工工作流非常重要。测试是输送管道的重要组成部分。除了单元和功能测试外,性能测试、持续负载测试和故障注入测试也很重要。操作准备审查,必须评估测试、监控的完整性,并能够根据SLA审计应用程序性能

自动化部署

使用高级部署技术,如

  • 金丝雀:通过监控影响,逐步引入更改并向前和向后移动
  • 蓝-绿:立即建立一个并行的新堆栈和交换流量(并根据需要快速回滚)
  • 功能切换-使用配置选项通过根据需要打开/关闭来部署新功能
  • 故障隔离区部署:使用故障隔离区隔离部署并围绕区域故障规划容量

测试

测试必须符合可用性目标。单元测试、负载测试、性能测试、故障测试和外部依赖性测试是必要的。

监控和警报

监控需要有效检测故障并发出警报。您最不希望的是客户在您之前知道问题。监控和警报系统应与主要服务分离,服务中断不应影响监控和警报。

监测分为五个阶段

产生

确定需要监控的服务、定义度量、创建阈值和相应警报。几乎所有AWS服务都提供大量监控和日志信息供用户使用。例如Amazon ECS和AWS Lambda流日志到CloudWatch日志,VPC流日志可以在VPC中的任何或所有ENI上启用

聚合

Amazon CloudWatch和S3是主要的聚合层。一些服务(如ASG和ELB)提供开箱即用的度量,其他流服务(如VPC流日志/CloudTrail事件数据)被转发到CloudWatch日志,这些日志可以被过滤以提取度量。这可以提供触发警报的时间序列数据。

实时处理和报警

警报可以与多个用户的SNS集成,或发送到SQS进行第三方集成,或使用AWS Lambda立即采取行动。

存储和分析

CloudWatch日志可以将日志发送到AmazonS3,EMR可以用于进一步了解数据。Splunk/Logstash等第三方工具可用于聚合/处理/存储和分析。数据保留要求是关键,旧数据可以移动到AmazonGlacier进行长期存档。

作战准备审查(ORR)

ORR对于确保应用程序可用于生产非常重要。团队需要有一份初始ORR检查表,必须重复以验证准确性。一个团队的ORR必须结合从其他应用中吸取的经验教训。

审计

审核监控方面以验证可用性目标至关重要。根本原因分析需要发现发生了什么。AWS提供以下服务以跟踪事件期间的服务状态

  • CloudWatch日志:存储日志并检查
  • AWS配置:随时查找基础设施的状态
  • AWS CloudTrail:查找由谁调用了哪些AWS API

请继续关注第2部分—高可用性体系结构,以实现特定的SLA

工具书类

SEO Title
Architecting for Reliability Part 1— Concepts

【可靠性架构】可靠性架构第2部分:云的弹性和可用性设计模式

Chinese, Simplified

提到https://en.wikipedia.org/wiki/Software_design_pattern详细概述了什么是设计模式,并参考了几种软件设计模式。本故事旨在回顾与云环境中的弹性和可用性相关的一些流行设计模式。

本故事的参考来自以下链接,所有图片均由各自的内容所有者提供。

可用性模式

可用性表示系统运行和工作的时间。它可能会受到系统维护、软件更新、基础架构问题、恶意攻击、系统负载和与第三方提供商的依赖关系的影响。可用性通常通过SLA和9来衡量。例如,“五个9”意味着99.999%的可用性,这意味着系统在一年内可以停机约5分钟。检查https://uptime.is/查找特定SLA的可用性

运行状况终结点监视

在云中,应用程序可能会受到几个因素的影响,如延迟、提供商问题、攻击者和应用程序问题。有必要定期监视应用程序是否正常工作。

解决方案大纲

  • 创建运行状况检查终结点
  • 端点必须进行有用的健康检查,包括存储、数据库和第三方依赖关系等子系统
  • 使用状态代码内容返回应用程序可用性
  • 以适当的时间间隔监控终点,以及距离客户较近的地点的延迟
  • 保护端点以防止攻击

有关完整概述,请参阅Microsoft链接

下图描述了AWS特定实现中的相同模式。这解释了健康检查应该有多深,而不是前面的静态页面。

有关详细信息,请参阅链接。

Other references

基于队列的负载调配

重载/频繁请求可能会使服务过载,从而影响可用性。通过对此类请求进行排队并异步处理,将有助于提高系统的稳定性。

解决方案大纲

  • 在任务和服务之间引入队列
  • 任务放置在队列中
  • 服务以所需的速度处理任务。在一些高级实现中,服务可能会根据队列大小自动缩放。
  • 如果需要响应,服务必须提供适当的实现,但是,这种模式不适合低延迟响应需求

有关完整概述,请参阅链接

其他参考资料

节流

限制服务或其组件或客户端使用的资源数量,以便即使在极端负载期间,服务也能继续运行,满足SLA要求

解决方案大纲

  • 设置单个用户访问的限制,监控指标并在超过限制时拒绝
  • 禁用或降级不重要的服务,以便关键服务能够正常工作,例如,视频通话只能在带宽问题期间切换到音频
  • 确定某些用户的优先级,并使用负载均衡来满足高影响客户的需求

有关完整概述,请查看链接

其他参考资料

弹性模式

弹性是系统从故障中优雅地恢复的能力。检测故障并快速高效地恢复是关键。

隔板(Bulk Head)

隔离应用程序组件,使其中一个组件的故障不会影响其他组件。隔板表示船舶的分段隔板。如果一个隔板受损,水只会在该隔板中,从而避免船舶沉没

解决方案大纲

  • 将服务实例划分为多个组并单独分配资源,以便故障不会消耗此池之外的资源
  • 根据业务和技术需求定义分区,例如,高优先级客户可能获得更多资源
  • 利用Polly/Histrix等框架,并使用Containers等技术提供隔离。例如,容器可以为CPU/内存消耗设置硬限制,以便容器的故障不会耗尽资源。

有关完整概述,请参阅链接

其他资源

断路器

当一个服务被认为已经失败,并且如果它继续运行可能会对其他应用程序产生负面影响时,它应该抛出异常,并且可以稍后在问题似乎已修复时恢复,可以恢复该服务

解决方案大纲

下图显示了使用状态机实现断路器

有关完整概述,请查看链接

其他参考文献

补偿事务处理

在分布式系统中,强一致性并不总是最佳的。最终的一致性会产生更好的性能和组件集成。当发生故障时,必须撤消前面的步骤。

解决方案大纲

  • 补偿事务将记录工作流的所有步骤,并在出现故障时开始撤消操作

下图描述了一个具有顺序步骤的示例用例。

补偿事务不必撤消完全相同的顺序,可以执行并行调用。

有关详细概述,请查看链接

其他参考文献

领导人选举

协调多个类似实例执行的操作。例如,多个实例可能正在执行类似的任务,可能需要协调,也可能避免对共享资源的争用。在其他一些情况下,可能需要汇总几个类似实例的工作结果。

解决方案大纲

单个任务实例应被选为领导者。这将与其他从属实例协调操作。由于所有事例都是相似的,并且是同行的,因此必须有一个强有力的领导人选举过程

领导人选举过程可以使用以下几种策略

  • 选择排名最低的实例或进程ID
  • 获取Mutex-当领导者断开连接或失败时,应小心释放Mutex
  • 实现常见的领导人选举算法,如Bully或Ring

此外,利用任何第三方解决方案,如Zookeeper,避免开发复杂的内部解决方案

有关详细概述,请查看链接

其他参考文献

重试

通过重试失败的操作来启用应用程序处理瞬时故障,以提高应用程序的稳定性

解决方案大纲

各种方法包括

  • 如果故障被视为非瞬时故障且不太可能修复,则取消
  • 如果故障看似异常,则立即重试,并且立即重试可能会成功
  • 如果故障看起来是临时问题,并且可能在短时间间隔后修复,例如API速率限制问题,请在延迟后重试。

重试尝试应谨慎,不应使已加载的应用程序紧张。此外,请考虑要重试的操作的安全性(Idemptent)

有关完整参考,请查看链接

其他参考文献

调度程序代理主管

协调更大的操作。当事情失败时,尝试恢复,例如使用重试模式并成功,但如果系统无法恢复,则撤消工作,以使整个操作以一致的方式失败或成功。

解决方案大纲

解决方案涉及3个参与者

  • 调度器-安排工作流中各个步骤的执行并协调操作。调度器还记录每个步骤的状态。调度器与代理通信以执行步骤。调度器/代理通信通常使用队列/消息传递平台异步进行
  • 代理-通过一个步骤封装调用远程服务引用的逻辑。每个步骤可能使用不同的代理
  • 主管-监视调度程序执行的任务中的每个步骤。在发生故障时,它请求由代理执行或由调度程序协调的适当恢复

下图显示了一个典型的实现

有关完整参考,请查看链接

其他参考文献

AWS特定模式

以下部分描述了一些显示特定AWS实现的模式。其中一些比较简单,但值得一看。

多服务器模式

在这种方法中,您可以在负载平衡器后面配置其他服务器,以提高数据中心/可用性区域内的可用性

您需要注意共享数据和粘性会话。利用其他数据访问模式解决此类问题

有关详细概述,请查看链接

多数据中心模式

这扩展了多服务器模式,通过在多个数据中心/可用性区域中创建服务器来解决数据中心故障

数据共享问题仍然如前一节所述。

有关完整概述,请查看链接

浮动IP模式

在这种情况下,应用程序会为服务器分配一个浮动IP,在发生故障时,该IP可以重新分配给另一个工作服务器。虽然这个想法是原始的,并且依赖于弹性IP特性,但是可以扩展该模式以实现高级架构。

有关完整概述,请查看链接

SEO Title
Architecting for Reliability Part 2 — Resiliency and Availability Design Patterns for the Cloud

【可靠性架构】可靠性架构第3部分:高可用性体系结构

Chinese, Simplified

可用性目标场景

在本节中,我们将回顾一个示例应用程序,并阐述部署架构如何因不同的可用性目标而变化。示例应用程序是一个典型的web应用程序,它具有反向代理、S3中的静态内容、应用程序服务器和SQL数据库。无论我们在容器还是虚拟机中部署它们,可用性设计都保持不变。

服务选择

我们将使用EC2进行计算,使用Amazon RDS进行关系数据库,并利用Multi-AZ部署。将使用路由53进行DNS,使用ELB分配负载,使用S3进行备份和静态内容。

99%(2个9)方案

应用特点

  • 根据可用性图表,这些应用程序每年的停机时间约为3天15小时。
  • 这些应用程序通常对业务有帮助,如果不可用,可能会带来不便(不是关键任务)。
  • 大多数内部系统都属于这一类别,并具有实验性的客户功能。

部署设计

  • 单个区域
  • 一个可用区域
  • 单个实例
  • 将备份数据发送到S3进行恢复,对对象启用版本控制,对备份禁用删除,存档/删除旧数据的生命周期策略
  • Cloudformation将基础设施定义为一个代码,并将用于在出现故障时加快整个基础设施的重建。
  • 故障期间,使用DNS更改,将流量路由到静态网站
  • 部署管道计划有基本单元/黑盒/白盒测试
  • 软件更新是手动的,需要停机
  • 监控查找主页的200 OK状态

可用性计算

在这种设计中,每次故障恢复大约需要70分钟。每次部署/软件更新需要4小时。估计大约有4次故障和6次其他更改,可用性达到99%。

99.9%(3个9)方案

应用特点

  • 根据可用性图表,这些应用程序每年的停机时间约为8小时45分钟。
  • 这些应用程序的高可用性很重要,但可以承受短暂的不可用时间。
  • 例如,关键的内部应用程序和低收入的面向客户的应用程序。

部署设计

  • 我们将利用利用多个可用区域的AWS服务。(ELB/ASG/RDS MultiAZ)
  • 负载平衡器将配置应用程序健康检查,该检查实际上描述了每个实例中应用程序的健康状况
  • ASG将替换运行状况检查失败的实例,RDS将故障转移到第二个AZ以处理主要AZ故障
  • 应用程序将分为不同的层(反向代理/应用程序服务器),以提高可用性。应用程序恢复模式将确保在AZ故障切换期间短暂的数据库不可用不会影响应用程序可用性
  • 使用就地方法自动更新软件,并在出现故障时记录回滚过程
  • 每2-4周按固定计划交付软件
  • 监控将检查主页上的200 OK状态、web服务器的更换、数据库故障切换和S3中的静态内容可用性
  • 将汇总日志以进行根本原因分析
  • 存在用于恢复和报告的Runbook
  • 行动手册适用于常见的数据库相关问题、安全相关事件、失败部署以及根本原因分析。

可用性计算

假设2次故障需要人工干预,每次事故60分钟,则影响将为2小时。假设自动软件更新需要每次停机15分钟,并且需要10个这样的实例,我们将需要150分钟的停机时间。这为我们提供了99.9%的可用性

99.99%(4个9)方案

应用特点

  • 根据可用性图表,这些应用程序的停机时间约为52分钟/年。
  • 这些应用程序必须具有高可用性,能够容忍部件故障,并且能够吸收故障而无需获取部件故障。
  • 例如电子商务应用程序和b2b web服务。
  • 我们应该通过在一个区域内保持静态稳定来进行设计。这意味着我们需要能够容忍一个AZ的丢失,而不需要提供新的容量或更改DNS等。。

部署设计

  • 在3个AZ中部署应用程序,每个AZ的容量为50%
  • 对于可以缓存的内容,请添加CloudFront以减少系统负载
  • 在所有层中实施软件/应用程序恢复模式
  • 设计主内容的读可用性而非写可用性
  • 利用故障隔离区部署策略
  • 部署管道还必须包括性能、负载和故障注入测试
  • 如果不满足KPI,部署应完全自动化并自动回滚
  • 监控应报告成功情况,并在出现问题时发出警报
  • 必须存在未发现问题和安全事件的行动手册
  • 使用游戏日测试失败程序

可用性计算

假设2次故障需要人工干预,每次事故15分钟,则影响将为30分钟。自动软件更新不需要停机。这为我们提供了99.99%的可用性

多区域部署

使用多个地理区域将以增加支出为代价对恢复时间提供更大的控制。区域提供了非常强的隔离边界。

Multi-Region Deployment Courtesy of http://harish11g.blogspot.com

使用多区域部署的99.95%(3.5个9)场景

应用特点

  • 根据可用性图表,这些应用程序每年的停机时间约为4小时。
  • 这些应用程序必须高度可用,需要非常短的停机时间和很少的数据丢失
  • 例如银行、投资和应急服务

部署设计

  • 99.95 % SLA
  • 跨两个区域使用热备用
  • 被动站点扩展并最终保持一致,以接收与主动站点相同的流量
  • 即使在1个AZ故障期间,两个区域也应保持静态稳定,以处理所有容量需求
  • 在所有层中实施软件/应用程序恢复模式
  • 将需要一个轻量级的路由组件来监控应用程序运行状况和区域依赖性。路由组件将自动化故障,停止复制
  • 故障切换期间,请求将被路由到静态网站
  • 软件更新将使用蓝绿/金丝雀部署方法
  • 部署管道还必须包括性能、负载和故障注入测试
  • 监视服务器/db/静态内容和区域故障并发出警报
  • 通过游戏日使用Runbook验证体系结构

可用性计算

假设2次故障需要人工干预,每次事故30分钟,则影响将为60分钟。自动软件更新不需要停机。这为我们提供了最高99.95%的可用性

99.999%(5个9)或更高的方案

应用特点

  • 根据可用性图表,这些应用程序每年的停机时间约为5分钟
  • 这些应用程序必须高度可用,并且不允许停机和数据丢失
  • 例如高收入银行、投资和关键政府职能

部署设计

  • 强一致性数据存储
  • 所有层完全冗余
  • 尽可能使用NoSQL数据库来改进分区策略
  • 利用主动/主动多区域方法。每个区域必须是静态稳定的
  • 路由层将向正常站点发送流量,并在故障期间停止复制
  • 在所有层中实施软件/应用程序恢复模式
  • 部署管道还必须包括性能、负载和故障注入测试
  • 软件更新将使用蓝绿/金丝雀部署方法
  • 如果不满足KPI,部署应完全自动化并自动回滚
  • 数据存储复制技术应自动解决冲突

可用性计算

假设所有恢复过程都是自动化的,并且具有冗余性,则影响将小于一分钟,预计将发生4次此类事件。自动软件更新不需要任何停机时间。这为我们提供了99.999%的可用性

本文:https://architect.pub/node/2273

SEO Title
Architecting for Reliability Part 3— High Availability Architectures

【高可用性】高可用性的架构模式

Chinese, Simplified

您可以查看有关不同体系结构模式的信息,这些模式可用于提高正常运行时间和提高应用程序弹性。

(DOM)应用程序通常部署在外部系统的集成网络中,以形成一个有凝聚力的业务生态系统。长时间的应用程序或系统停机可能会产生严重的业务后果。

解耦和组件独立是一种非常强大的体系结构模式,可以将整个生态系统解决方案的关键部分与其他领域的停机或故障隔离开来。通过在解决方案设计期间采用以下一种或多种模式,可以大大提高基于解决方案的可用性和正常运行时间。这些模式中的每一种都可以使应用程序的一个或多个部分与其他部分分离,从而为外部用户和客户等关键领域提供更高的可用性和正常运行时间。

这些设计模式中的每一种都可以被应用以提供增加的应用弹性。虽然这些示例讨论了网站集成,但这些模式也可以应用于其他集成领域。

围绕系统设计良好的解决方案实际上可以将整个解决方案的可用性和正常运行时间提高到高于开箱即用的水平。例如,在某些关键领域,即使产品计划内或计划外停机,解决方案也可以继续可用。

最后,与基于技术和冗余的解决方案相比,还有一些其他与流程和部署相关的解决方案设计考虑因素实际上可以以更低的成本提供更好的可用性和正常运行时间。

异步集成作为一种解耦技术

您可以使用异步集成作为一种解耦技术,以允许在外部系统仍然可用时不可用。

缓存作为一种解耦技术

当使用缓存作为去耦技术时,消费应用程序(例如,Web商店)从本地数据缓存中获取诸如项目属性、库存余额或项目可用性等信息。这种方法减少了同步查询的需要。

代码、配置和修复程序的热部署

虽然所提供的方法和设计模式使解决方案的关键领域免于停机,但有一些部署技术是由的体系结构提供的或其固有的,允许您在关键的同步应用程序组件上热部署增量更改、配置和修复。

部署过程和回归测试

可以显著影响应用程序可用性和正常运行时间的最重要和最容易被忽视的领域之一是,存在一个严格执行的过程来促进、表征、验证和回归测试增量推出或修复包和升级。

SEO Title
Architectural patterns for high availability

【高可用架构】高可用性设计模式

Chinese, Simplified

使用日常商业质量的硬件和软件,可以实现“五个9”的可靠性。关键是这些组件的组合方式。

我们的社会已经开始期待它使用的许多系统提供不间断的服务,例如电话、自动柜员机和信用卡验证网络。其中许多被实现为嵌入式系统。

嵌入式设计人员越来越多地被要求创建能够可靠运行的系统,达到99.999%的时间(称为“五个9”可用性),这相当于每天不到1秒的停机时间。这些系统称为高可用性系统。

高可用性系统的设计基于冗余硬件组件和软件的组合,以管理故障检测和纠正,而无需人工干预。在本文中,我们将快速回顾一些与高可用性和故障管理相关的定义,然后继续讨论容错系统的一些硬件和软件设计模式。


故障与故障(Fault vs. failure)

当我们设计高可用性系统时,我们需要将大部分设计工作集中在故障和故障上。为了更好地定义,我们可以将故障(failure )定义为系统提供的服务不符合其规范的情况。我更喜欢一个将系统提供的服务与我们的期望进行比较的定义,而不是一个规范。但我们的期望往往是主观的,没有很好的文档记录。因此,我们将坚持将系统的服务与其规范进行比较,尽管这会让我们面临来自规范错误或遗漏的问题。

另一方面,故障( fault)是交互系统的故障。这就是我们所认为的不希望发生的事情的可能原因。因此,故障可能是我们系统的子系统故障、组件故障、外部系统故障或编程错误。故障会引发更多的各种故障。或者它们会引发失败。或者,它们可以在不引发任何失败的情况下发生。

例如,故障可能是卡车司机没有遵守金门大桥的负载限制。如果卡车超过负载极限20%或30%,我们预计桥梁不会损坏。但另一个故障可能是同一辆卡车撞上了桥梁道路的中间分隔带。这也不会导致大桥发生物理故障,但可能会导致大桥在数小时内无法实现将人员和车辆穿过金门水道的特定目的。

故障可能是暂时性、永久性或间歇性的。当它们被激活时,可能会导致系统或子系统的状态出错。这些错误可能会引发系统故障。处理故障有四种主要方法:

  • 故障预测(Fault forecasting)
  • 故障避免 (Fault avoidance)
  • 故障排除 (Fault removal)
  • 容错性 (Fault tolerance)

故障预测使用数学模型和实际实验来提供故障存在及其后果的估计。例如,一种实用的故障预测技术是将故障注入系统,并研究任何由此产生的故障。

通过使用严格的系统、硬件和软件开发过程(可能包括正式规范和验证技术)来实现故障避免和排除。

容错是通过使用冗余的、可能是多样的系统实现来实现的,以避免故障的影响。实现容错的一种方法被称为“优雅降级”(或“软故障”)——如果不能提供完整的系统性能,则提供合理的部分功能。另一种方式被称为“故障安全”(或“故障停止”)-当出现故障时,将系统停止在安全状态,而不是继续运行。

容错的主要概念是冗余。它基于这样的想法(或希望),即多个独立的故障不会一起袭击您的系统。应设计容错系统以避免单点故障。换言之,如果系统的一部分可能发生故障,那么系统中应该有一个冗余部分可以弥补故障,从而避免故障。

冗余有多种形式:

  • 硬件冗余(低级、高级或两者)
  • 软件冗余
  • 时间冗余
  • 信息冗余

硬件冗余的例子包括自检逻辑电路和一架飞机上的多个飞行计算机。软件冗余可能使用两种完全不同的算法来计算相同的结果。时间冗余可以通过通信重新传输来实现。信息冗余可以使用备份、校验和和纠错码来实现。

冗余可以是动态的或静态的。两者都使用复制的系统元素。在静态冗余中,所有副本同时处于活动状态。如果一个复制副本“抛出错误”,则可以立即使用其他复制副本以允许系统继续正确操作。在动态冗余中,一个副本是活动的,其他副本是被动的。如果主动复制副本引发故障,则先前被动复制副本将被激活并接管关键操作。

那么,所有这些与实现高可用性有什么关系呢?首先,一个定义。高可用性是指系统能够容忍故障并根据其规范继续提供服务的能力。系统可以使用此处描述的所有概念和方法来实现高可用性。

可用性通常以“可用性百分比”或“每年停机时间”为单位来衡量。典型的容错系统可能在99.99%的时间内可用,或每年停机不到一小时(每天10秒)。但高可用性系统预计在99.999%的时间内可用,或者每年可用时间不到五分钟(大约每天一秒)。这通常意味着,当出现故障时,必须自动处理。人类太慢,无法在所需的时间内消除或掩盖任何问题。

硬件冗余

与其将硬件构建为由超级可靠组件构建的单个超级可靠模块,不如使用由日常商业质量组件构建的日常商业质量硬件的冗余复制模块通常更具成本效益。

每个复制副本通常都设计为表现出“快速故障”或“故障停止”行为。这大大简化了故障管理决策:每一次故障都会使硬件停止运行;而不是试图一瘸一拐地向故障管理器挑战,以找出模块的哪些输出现在有故障,哪些输出仍然良好。

对于使用静态冗余的容错,每个复制模块可以具有日常商业可靠性。使用两个副本称为配对或双工。如果使用N个副本,则称为N丛。

图1:三重冗余硬件

图1显示了一种3倍或三倍冗余的硬件设计。三个副本显示在图表底部附近。它们将它们的输出提供给“投票器”,后者决定子系统的实际最终输出。当N≥3时,“投票人”通常使用多数决策。但是,这需要是大多数未失败的副本,而不仅仅是副本总数(失败和未失败)的简单多数。

但是,选民不只是一个硬件和软件,可能会像我们系统中的任何其他模块一样出现故障吗?事实上,它可以;如果这样做的话,会给我们的系统带来灾难。但选民通常是非常简单的单位,可以设计和测试以确保其稳健性。或者,您可以创建涉及复制选民和选民的二级选民等的设计。但我们这里不讨论这一点。

对于使用动态冗余的容错,复制的模块仍然具有日常商业可靠性。一种方法是使用由一个活动模块和一个备用模块组成的冗余对。另一种方法是使用模块集群。这些模块不必彼此精确复制,可以具有不同的特性、接口和容量。集群需要故障切换策略来决定当主模块引发故障时如何管理多个模块。以下是一些选择:

  • 备用备份(Standby backup)。当主模块在系统中运行时,一个备份模块处于“待机”状态,监视主模块是否存在故障,并准备启动并接管。例如,可以使用这种方法设计高可用性web服务器。
  • 旋转备用(Rotating standby)。当主模块在系统中运行时,可能有多个备份模块。主系统出现故障时,一个备份将接管系统的运行。航天飞机上的飞行计算机是按照这样的理念设计的:主模块由一对计算机组成,它们必须始终彼此一致。第一个备份模块是一对类似的模块。但航天飞机上的第二个备用模块是一台计算机,只能通过人工指挥才能接管。
  • 故障切换到非关键模块(Failover to non-critical module)。主模块运行系统的关键资源。备份模块可以运行其他非关键功能,但在发生故障时,它可以接管主模块的最关键服务。作为人类,当我们试图发送紧急电子邮件时,电脑的高速互联网连接出现故障,我们会迅速切换到我们从未想过会再次需要的旧调制解调器。
  • 相互接管(Mutual takeover)。每个模块运行自己的关键资源,但在发生故障时可以接管另一个模块的关键资源。例如,在心脏重症监护病房中,每8名患者应有一台心脏监测计算机。但是,如果相邻的心脏监测计算机出现故障,每台计算机可以处理另外八名患者(可能有一些轻微的退化)。

故障切换的正确实施至关重要。如果引发故障的主模块继续运行,同时另一个模块试图接管其服务,这将是一场灾难。他们的服务可能会以意想不到的方式发生冲突。如果一个主模块在抛出故障后被停止,而没有其他模块来接管它的服务,这可能同样是灾难性的。因此,故障切换的验证和测试是至关重要的,尽管这不是我们很多人喜欢做的事情。

软件冗余

大多数硬件故障都是随机的,是由物理缺陷造成的,这些缺陷要么在制造过程中持续存在,要么随着组件磨损或受到周围物理世界的冲击而发展。另一方面,软件故障不是物理故障;软件不会磨损。相反,软件故障是由于调用包含软件设计或实现中始终存在的缺陷的软件路径而导致的。由于软件通常比硬件更复杂,因此可以预期它具有更多的内置缺陷,从而导致比硬件故障更多的软件故障。软件容错设计成本也比硬件容错高。

N版本编程是一种成熟的软件容错设计模式。当我在70年代第一次遇到它时,它被称为不同的软件。它是硬件N复用的软件等价物(见图1)。但这并不像硬件N丛的复制那样简单,即同一软件的N个副本将包含相同的错误,并产生N次相同的错误。在N版本编程中,如果某些软件功能的N个单元需要并行运行,它们需要是该功能的N种不同实现,由N个独立的开发团队独立实现。这是N版编程。

1996年6月,阿丽亚娜-5号卫星发射火箭的第一次飞行在到达4000米的高度时发生了火球爆炸。尽管存在硬件冗余,但火箭惯性参考系统(其数字飞行控制的一部分)的故障导致了故障,因为软件冗余没有得到妥善处理。阿丽亚娜-5号上有两台惯性参考计算机,一台处于活动状态,另一台处于“热”备用状态。两者都并行运行,硬件和软件完全相同。该软件与阿丽亚娜-4号上的软件几乎相同,阿丽亚娜4号是一款较旧且成功的运载火箭。但阿丽亚娜-5号上的一些飞行参数值大于阿丽亚娜-4号,因此数据值溢出。该错误是通过关闭计算机来处理的。由于冗余计算机运行的是相同的软件,它也受到了数据溢出的影响,而且很快就被关闭了,整个惯性参考系统都死了。结果,发动机的喷嘴旋转到极端位置,导致火箭突然转向并在自毁前破裂。[1] 数据溢出错误的处理方式适用于随机发生的硬件错误,但不适用于两台计算机上发生的类似软件错误。两台计算机上类似的软件错误可以通过N版本编程避免。

回到70年代,我们认为N版本编程是软件容错的最先进技术。从那时起,这种设计模式出现了许多问题:当你使用它时,软件开发成本飙升,因为你需要支付N个独立的小组来实现N个独立软件设计。但是,如果你试图节省一些成本,你会遇到所谓的“平均智商”问题:成本较低的开发团队拥有资质较差的软件工程师,他们会产生质量较低的代码。因此,你可能会得到N个不同的程序,这些程序都充满了错误,以N种不同的方式创建。

N版本编程的另一个失败是向N个独立开发团队提供什么作为输入的问题。一般来说,一个规范被影印并提供给所有N个开发团队。但是如果这个规范有缺陷,你会得到N个独立开发的类似缺陷软件版本,它们都会做错事。如果在系统发布后发现了规范或使用错误,那么在N个不同的实现中,每个新错误必须被修复N次,从而使维护成本过高。如今,人们通常认为,让一个顶级软件开发团队使用最好的可用基础设施、软件开发工具、技术和测试开发一个高质量的软件版本,可以更好地利用N版本编程的价格。

检查点

与N版本编程的静态冗余不同,许多软件容错设计模式基于动态冗余。它们都采取四个阶段的方法:

  • 错误检测
  • 损害评估和限制(有时称为“防火墙”)
  • 错误恢复
  • 故障处理和持续服务

在这些阶段中的第二阶段,当检测到软件错误时,通常采用故障停止方法。但软件是高度复杂的,因此,如何消除围绕错误的错误软件行为的影响通常是不清楚的。在这方面,一个有用的工具是交易的概念。事务是对应用程序状态的操作的集合,因此事务的开始和结束是应用程序处于一致状态的点。例如,每个城市的市政厅都有一个文件系统,其中包含该城镇所有居民的信息。当两个人结婚时,他们的名字和结婚日期都记录在一个名为“已婚夫妇”的文件中。此外,新郎的身份在名为“男性居民”的文件中将从单身变为已婚。新娘的身份在称为“女性居民”的文件中将从单身变成已婚。“如果三个文件更新中的一个失败,或者软件在一路上崩溃,我们需要回到婚姻”交易的开始。“否则,我们可能会出现不一致的状态,比如新郎被列为已婚,而他的妻子仍然被列为单身。”。只有在婚姻交易开始时,以及婚姻交易成功结束时,情况才是一致的。

如果我们想使用事务的概念来容错,我们的系统必须能够在事务开始时保存其状态。这叫做检查点。它包括在即将开始新事务的第一步时对软件状态进行“快照”。仅当上一个事务在无错误状态下完成时,才会拍摄快照。这里的基本恢复策略是重新执行:当在事务期间检测到错误时,事务将失败停止,系统将重新加载回上次保存的检查点。然后从该检查点继续服务,允许新事务建立在其一致状态上。但是,失败停止的事务将丢失。这种错误恢复被称为向后错误恢复,因为软件状态被回滚到过去的无错误点。

图2:检查点回滚场景

简单的检查点有自己危险的单点故障。在拍摄检查点本身的快照过程中可能会出现故障。但有一种解决方案,有时称为检查点回滚。如图2所示。在该图中,省略号表示通过队列发送消息来彼此通信的软件客户端和软件服务器。单个事务可能包括从客户端到服务器的许多请求消息,以及从服务器到客户端的许多响应消息。在事务处理期间,数据在服务器内被修改。在事务结束时,应在右侧显示的两个永久性大容量存储设备中的每一个上记录一组一致的数据。应连同数据一起记录交易序列号。如果稍后检测到错误并且服务器已停止,则可以重新启动此服务器(或启动副本服务器)。作为启动恢复过程的一部分,将检查两个大容量存储设备上的事务序列号。服务器数据将从包含最高序列号的设备中恢复。(另一个大容量存储设备可能包含较低的序列号,因为故障发生在该设备的检查点期间。)

进程对

这种检查点设计模式的一个限制是故障后的恢复可能需要很长时间。启动或重新启动服务器可能需要大量处理,也可能需要将数据恢复回检查点。“热备份”服务器直接使用其自身的永久性大容量存储设备,可以加快恢复速度。这种设计模式称为过程对;如图3所示。

图3:流程对

在这里,我们看到位于图中心的主服务器的工作情况与前面的检查点场景中的工作情况非常相似。客户端直接使用此主服务器。每当主服务器成功完成整个事务时,它就会将有关其新的一致状态的信息传递给备份服务器(右侧)。主服务器和备份服务器都将数据记录在其永久性大容量存储设备中。通过这种方式,备份服务器可以随时了解已完成的事务。当主服务器启动并可供客户端使用时,它会定期向备份服务器发送心跳消息。这些心跳消息可以与一些检查点消息组合。如果备份服务器检测到心跳消息流已停止,则它知道主服务器已停止或不可用,并且它将很快接管新的主服务器。

当客户端、主服务器和备份服务器都在不同的处理器或模块上时,以及当它们都在一个处理器上时,这种设计模式可以工作。

尽管过程对设计模式非常复杂,但仍存在一些问题。例如,检查点消息可能会丢失或无序到达备份服务器。或者,如果主服务器是物理设备的控制器,并且在操作过程中发生故障,则可能会出现问题。备份服务器在接管时可能不知道如何完成操作,因为它不知道主服务器在发生故障之前走了多远。(例如:当发生故障时,主服务器已将核反应堆的石墨棒移动了所需的30cm。)

同样,在流程对设计模式中,当主服务器发生故障时正在进行的事务很可能在执行过程中丢失或丢弃。备份服务器将以主服务器在失败之前向其报告的上次完成事务的状态进行接管。

恢复块

动态软件冗余的另一种设计模式称为恢复块。它基于检查点,但它增加了对软件处理结果的验收测试。您需要像N版本编程一样准备许多处理数据的替代方法,但您并没有为每个事务运行所有处理替代方法。相反,您选择一种处理数据的方法作为主要替代方法,并首先尝试仅使用主要替代方法的处理来执行事务。在主处理结束时,运行验收测试。如果通过了验收测试,你就完成了。如果验收测试失败,则继续尝试下一个替代处理,如图4所示。

图4:恢复块

如图所示,在首次进入恢复块之前,必须执行检查点操作。每次验收测试失败后,软件必须回滚到检查点状态。验收测试是在尝试的每个处理备选方案之后进行的。以这种方式,在处理备选方案成功交付通过验收测试的结果之前,将运行处理备选方案。这些“良好”输出构成了恢复块的最终结果。

前向错误恢复

检查点回滚、进程对和恢复块都是执行向后错误恢复的方法。大多数动态软件容错是使用反向错误恢复来完成的,但正向错误恢复是另一种选择。它的主要思想是从错误状态继续,并进行纠正,以清理受损状态。前向错误恢复取决于准确的损伤评估,通常是系统特定的。前向错误恢复的一个例子是异常处理,它在检测到问题时将控制权传递给专门的异常处理软件,而不是回滚并从以前的检查点状态继续。

前向错误恢复的一种设计模式称为替代处理。当一个事务有两个(或多个)处理备选方案时,可以使用此方法,其中一个备选方案通常非常精确但计算复杂,另一个备选更简单且性能更高。如果主处理出现故障,则第二个备选方案可以用作测试和辅助结果提供程序。例如,平方根算法可以是主要处理,表查找插值可以是其替代方法。一旦算法运行完毕,可以使用表查找插值来测试平方根算法结果的质量,并快速修复这些结果中的一些错误。

图5:飞机飞行控制的替代处理

在图5中,我们看到两个数字飞行控制系统同时运行,以控制一架飞机(波音777)。[2] 图右侧的决策逻辑使用更简单的飞行控制系统的输出作为测试复杂的主飞行控制系统输出的标尺。如果验收测试失败,那么更简单的飞行控制系统的输出也可以作为失败的主要输出的替代。(向左的箭头表示替代处理的结果也可用于向主处理提供反馈。)

这样的设计模式允许将日常商业质量的硬件和软件用作真正高可用性系统的构建块,这些系统可以在无需人工干预的情况下实现“五个9”或更高的可用性。

David Kalinsky是OSE Systems的客户教育总监。他是嵌入式软件技术的讲师和研讨会领导者。近年来,David建立了软件工程方面的高科技培训项目,以开发实时和嵌入式系统。在此之前,他参与了许多嵌入式医疗和航空航天系统的设计。大卫拥有耶鲁大学核物理学博士学位。可以在联系到他。

尾注

SEO Title
Design Patterns for High Availability