Chapter5 可用性

目录

可用性一般情景

提高可用性的策略

检测故障

从故障中恢复

预防故障

可用性设计清单

总结


"生活的百分之九十就是出现。"
- 伍迪·艾伦

可用性是指软件的一个属性,即当需要时,它应该存在并准备好执行任务。这是一个广泛的观点,包括通常所说的可靠性(尽管它可能还包括其他方面的考虑,如定期维护造成的停机时间)。实际上,可用性是建立在可靠性概念之上的,通过添加恢复的概念,即系统发生故障时能够自行修复。修复可以通过各种手段来完成,我们将在本章中看到。更准确地说,A·维吉尼斯和他的同事已经定义了可信性:

可信性是避免故障超出可接受范围更频繁和更严重的能力。

我们对可用性的定义作为可信性的一个方面如下:“可用性是指系统掩盖或修复故障的能力,以使累积的服务中断时间不超过指定时间间隔内的要求值。”这些定义使故障的概念受到外部代理的判断,可能是人类。它还包含了可靠性机密性完整性以及涉及到不可接受故障概念的任何其他质量属性。可用性与安全性密切相关。拒绝服务攻击明确旨在使系统失败,即使它不可用。可用性还与性能密切相关,因为很难判断系统何时发生故障以及何时只是响应速度极慢。最后,可用性与安全性密切相关,后者关注防止系统进入危险状态,以及在进入危险状态时恢复或限制损害。 

从根本上说,可用性是通过减轻故障来最小化服务中断时间的方式。故障意味着对环境中的系统或人类观察者的可见性。换句话说,故障是系统与其规范的偏差,偏差在外部可见。在构建高可用性、容错系统中最具挑战性的任务之一是了解在操作过程中可能发生的故障的性质(请参见“面向失败的规划”侧边栏)。一旦了解了这些故障,就可以将缓解策略设计到软件中。

故障的原因被称为故障。故障可能是系统内部或系统外部的。在故障发生和故障发生之间的中间状态称为错误。可以预防、容忍、消除或预测故障。这样一来,系统就变得对故障“有弹性”。

我们关心的领域包括如何检测系统故障、系统故障可能发生的频率、故障发生时会发生什么、系统被允许停机的时间有多长、何时可以安全地发生故障或故障如何可以预防以及故障发生时需要什么样的通知。

由于系统故障对用户是可见的,因此修复时间是指故障不再可见的时间。这可能是响应时间的短暂延迟,也可能是某人飞到安第斯山脉的偏远地区修理一台采矿机械的时间(正如一个负责修理采矿机械引擎软件的人所告诉我们的)。 “可观察性”的概念可能是一个棘手的问题:例如,St

uxnet病毒长时间未被察觉,尽管它造成了损害。此外,我们通常关心故障发生后仍保留多少能力的水平,即降级操作模式。

故障和故障之间的区别允许讨论自动修复策略。也就是说,如果包含故障的代码被执行,但系统能够从故障中恢复,而不可观察到规范行为的任何偏差,那么就没有故障。

系统的可用性可以计算为在指定时间间隔内提供指定服务的概率。在涉及硬件时,有一个常用的表达式用于推导稳态可用性:

                                                

在这个公式中,MTBF表示故障间平均时间,MTTR表示平均修复时间。在软件领域,这个公式应该被解释为,在考虑可用性时,你应该思考什么会导致你的系统出现故障,出现故障的可能性有多大,以及需要一定时间来修复它

从这个公式中,可以计算概率并做出如“99.999%可用性”或系统在需要时不可操作的概率为0.001%之类的声明。

计划停机(当系统被故意停止使用)在计算可用性时可能不会被考虑,因为在那时系统被认为是“不需要的”;当然,这取决于系统的具体要求,通常编码在服务级别协议(SLAs)中。这种安排可能导致看似奇怪的情况,即系统已经停机,用户正在等待,但停机是计划的,因此不会被计入任何可用性要求。

在操作系统中,故障在报告和修复之前被检测和关联。故障关联逻辑将根据其严重程度(严重、主要或次要)和服务影响(影响服务或不影响服务)对故障进行分类,以便为系统操作员提供及时和准确的系统状态,并允许采用适当的修复策略。修复策略可以是自动化的,也可以需要手动干预。

计算机系统或托管服务提供的可用性通常以服务级别协议来表示。该SLA规定了所保证的可用性水平,通常还规定了计算机系统或托管服务如果违反SLA将承受的处罚。亚马逊为其EC2云服务提供的SLA是

亚马逊将采取商业上合理的努力,使Amazon EC2在服务年度内至少99.95%的年度正常运行时间百分比[在其他地方定义]可用。如果Amazon EC2没有达到年度正常运行时间承诺,您将有资格获得如下所述的服务信用。

表5.1提供了系统可用性要求的示例,以及在90天和一年的观察期内的可接受系统停机时间的相关阈值。术语“高可用性”通常指的是针对可用性达到99.999%(“5个9”)或更高的设计。根据定义或约定,只有未经计划的停机才会导致系统停机。

可用性一般情景

从这些考虑中,我们现在可以描述可用性一般情景的各个部分。这些部分总结在表5.3中:

刺激源 (Source of stimulus). 我们区分内部和外部的故障或故障的起因,因为期望的系统响应可能会不同。

刺激 (Stimulus). 以下类别中的一种故障发生:

   • 省略 (Omission). 一个组件未响应输入。
   • 崩溃 (Crash). 组件反复遭受省略故障
   • 时序 (Timing). 一个组件响应,但响应早或晚
   • 响应 (Response). 一个组件以不正确的值响应
   • 工件 (Artifact). 这指定需要高度可用的资源,如处理器、通信通道、进程或存储。

环境 (Environment). 在故障或失败发生时,系统的状态也可能影响期望的系统响应。例如,如果系统已经出现了一些故障并且正在以正常模式之外的方式运行,可能希望完全关闭它。但是,如果这是首次观察到的故障,可能更希望响应时间或功能的某种程度的降级。

响应 (Response). 对系统故障有多种可能的反应。首先,必须在采取其他任何响应之前检测和隔离故障。 (一个例外情况是在故障发生之前防止故障的情况。) 在检测到故障后,系统必须从中恢复。 与这些可能性相关的操作包括记录故障通知选择的用户或其他系统,采取措施限制故障造成的损害,切换到具有较低容量或较少功能的降级模式,关闭外部系统,或在维修期间变得不可用。

响应措施 (Response measure). 响应措施可以指定可用性百分比,或者可以指定检测故障的时间,修复故障的时间,系统必须保持可用的时间(这是指系统在特定时间段内必须保持可用的时间,可能是每天的某个时间段或特定的运营时间),或系统必须保持可用的持续时间(这表示系统必须在一段连续的时间内保持可用,例如,一个系统必须在一个月内持续保持可用)。

图5.3展示了从一般情景中生成的具体情景:心跳监视器在正常运行期间确定服务器没有响应。系统通知操作员并继续正常运行,没有停机

提高可用性的策略

系统不再按照其规范提供一致的服务时就会发生故障;系统的操作者可以观察到这种故障。故障(或故障的组合)有可能引发故障。因此,可用性策略旨在使系统能够经受系统故障,以便由系统提供的服务仍然符合其规范。本节中我们讨论的策略将防止故障演变成故障,或至少限制故障的影响并使修复成为可能。我们在图5.4中以示例说明了这种方法。

可用性策略可以归为以下三个类别:故障检测故障恢复故障预防。可用性策略的分类如图5.5所示。请注意,通常情况下,这些策略可能会由软件基础架构(如中间件包)为您提供,因此作为架构师,您的工作通常是选择和评估(而不是实施)合适的可用性策略和策略的正确组合。

检测故障

在系统采取任何故障处理措施之前,必须首先检测或预测到故障的存在。属于这个类别的策略包括以下内容:

Ping/echo(Ping/echo)是指在节点之间交换的异步请求/响应消息对,用于确定通过关联的网络路径的可达性和往返延迟。但回显还确定了被ping的组件是否正常运行并正确响应。Ping通常由系统监视器发送。Ping/echo需要设置时间阈值;该阈值告诉pinging组件在考虑pinged组件失败("超时")之前等待回显的时间。通过IP互连的节点可以获得ping/echo的标准实现。

Monitor(监视器)。监视器是用于监视系统的各个其他部分的健康状态的组件:处理器、进程、I/O、内存等等。系统监视器可以检测网络或其他共享资源的故障或拥塞,例如来自拒绝服务攻击。它协调使用本类中的其他策略来检测故障的组件。例如,系统监视器可以启动自测,或者是检测到故障的时间戳或错过的心跳的组件1

1. 当检测机制使用定期重置的计数器或计时器实现时,这种特殊化的系统监视器称为“看门狗”(watchdog)。在正常操作期间,被监视的进程将定期重置监视器中的看门狗计数器/计时器,作为它正常工作的信号;这有时被称为“抚摸看门狗”。

心跳(Heartbeat)是一种故障检测机制,采用系统监视器和被监视进程之间的定期消息交换。心跳的一个特殊情况是,被监视的进程定期重置其监视器中的看门狗计时器,以防止其过期并因此发出故障信号。对于关注可扩展性的系统,可以将心跳消息与被监视的进程和分布式系统控制器之间交换的其他控制消息一起传递,以减少传输和处理开销。心跳和ping/echo之间的主要区别在于执行健康检查的责任由监视器或组件本身负责。

时间戳(Time stamp)。这种策略用于检测事件的不正确顺序,主要用于分布式消息传递系统。事件的时间戳可以通过将本地时钟的状态分配给事件来建立,即事件发生后立即分配本地时钟的状态。如果时间信息不重要,也可以使用简单的序列号来实现此目的。

合理性检查(Sanity checking)检查组件的特定操作或输出的有效性或合理性。这种策略通常基于对内部设计、系统状态或受审查信息的了解。它通常用于接口,以检查特定信息流。

条件监视(Condition monitoring)涉及检查过程或设备的条件,或验证设计期间所做的假设。通过监视条件,这种策略可以防止系统产生故障行为。计算校验和是这种策略的一个常见示例。但是,监视器本身必须是简单的(理想情况下可证明的),以确保它不引入新的软件错误。

投票(Voting)。这种策略的最常见实现被称为三模块冗余(TMR),它采用三个执行相同操作的组件,每个组件接收相同的输入,并将其输出发送到用于检测三个输出状态之间不一致性的投票逻辑。面临不一致性时,投票者会报告故障。它还必须决定使用哪个输出。它可以让多数原则决定,或者选择计算出的不同输出的平均值。这种策略对投票逻辑具有关键依赖,通常实现为简单的、经过严格审查和测试的单例,以降低出错的概率。

• 复制(Replication)是投票的最简单形式;在这里,组件是彼此的精确克隆。拥有多个相同组件的副本可以有效地防止硬件的随机故障,但不能防止硬件或软件的设计或实现错误,因为这种策略中没有嵌入多样性。

• 功能冗余(Functional redundancy)是一种投票形式,旨在解决硬件或软件组件的共模故障(设计或实现故障)问题。在这里,组件在相同输入的情况下必须始终产生相同的输出,但它们的设计和实现是多样化的。

• 分析冗余(Analytic redundancy)不仅允许组件的私有端之间多样性,还允许组件的输入和输出之间多样性。这种策略旨在通过使用单独的需求规范来容忍规范错误。在嵌入式系统中,分析冗余还有助于处理一些输入源可能在某些时候不可用的情况。例如,航空电子程序可以通过多种方式计算飞行器的高度,如使用气

压、雷达高度计,以及使用地面前方点的直线距离和下视角度来计算。与分析冗余一起使用的选民机制需要比简单的多数原则或简单平均更复杂。它可能需要了解哪些传感器当前可靠,哪些不可靠,可能需要在时间内混合和平滑个别值以产生更高保真度的值。

异常检测(Exception detection)是指检测改变执行正常流程的系统条件。异常检测策略可以进一步细化:

• 系统异常(System exceptions)。系统异常将根据所采用的处理器硬件架构而变化,包括除零、总线和地址故障、非法程序指令等等。

• 参数围栏(The parameter fence)。参数围栏策略包括在对象的可变长度参数之后立即放置一个先验数据模式(例如OxDEADBEEF)。这允许在运行时检测用于对象的可变长度参数的内存分配是否被覆盖。

• 参数类型化(Parameter typing)使用一个基类,该基类定义了添加、查找和遍历类型-长度-值(TLV)格式消息参数的函数。派生类使用基类函数来实现根据每个参数的结构提供参数类型化的函数。使用强类型来构建和解析消息的实现比简单将消息视为字节桶的实现具有更高的可用性。当然,所有设计都涉及权衡。当您使用强类型时,通常会在可用性和演进的便利性之间进行权衡。

• 超时(Timeout)是一种策略,当组件检测到自己或另一个组件未能满足其时间约束时,会引发异常。例如,等待另一个组件的响应的组件可以在等待时间超过某个值时引发异常。

自测(Self-test)。组件(或更可能是整个子系统)可以运行自我测试过程来测试其正确操作。自测过程可以由组件自己启动,或者由系统监视器不时调用。这可能涉及到使用条件监视中找到的一些技术,如校验和。

从故障中恢复

从故障中恢复的策略可以细化为准备和修复策略 preparation-and-repair 以及重新引入策略 reintroduction tactics。后者涉及将已失败(但已恢复)的组件重新引入正常操作。

准备和修复策略 preparation-and-repair 基于多种重试计算或引入冗余的组合。它们包括以下内容:

主动冗余(热备份)Active redundancy (hot spare).。这指的是一种配置,其中保护组中的所有节点(主动节点或冗余备用节点)以并行方式接收和处理相同的输入,允许冗余备用节点与活动节点保持同步状态。因为冗余备用具有与活动处理器相同的状态,所以它可以在几毫秒内接管失败的组件。一个主动节点和一个冗余备用节点的简单情况通常被称为1 + 1("一加一")冗余。主动冗余也可以用于设施保护,其中使用主动和待机网络连接来确保高度可用的网络连接。

2. 保护组是一个处理节点组,其中一个或多个节点是“活动的”,其余节点是冗余备用。

被动冗余(温备份) Passive redundancy (warm spare)。这指的是一种配置,其中保护组中只有活动成员处理输入流量;它们之一的职责是定期向冗余备用节点提供状态更新。由于冗余备用节点维护的状态与保护组中活动节点的状态松散耦合(松耦合程度取决于活动节点和冗余节点之间的检查点机制),因此冗余节点被称为温备份。根据系统的可用性要求,被动冗余提供了一个在更高可用性但计算密集度(和成本)更高的主动冗余策略和可用性较低但复杂性明显较低的冷备份策略之间取得平衡的解决方案(这也显著便宜)。 (有关实施被动冗余的示例,请参阅第19章中的代码模板部分。)

备用(冷备份) Spare (cold spare)。冷备份是指冗余备用组件保持不使用,直到发生故障切换,此时在将冗余备用组件投入使用之前会启动一种上电复位过程。由于其较差的恢复性能,冷备份更适合具有高可靠性(MTBF)要求而不是具有高可用性要求的系统。

异常处理 Exception handling。一旦检测到异常,系统必须以某种方式处理它。它可以做的最简单的事情就是崩溃,但当然从可用性、可用性、可测试性和纯粹的常识角度来看,这是一个糟糕的主意。有更多更有效的可能性。用于异常处理的机制在很大程度上取决于所采用的编程环境,从简单的函数返回代码(错误代码)到使用包含有助于故障相关的信息的异常类(如引发异常的名称、异常的来源和异常引发原因)的使用。然后,软件可以使用这些信息来屏蔽故障,通常是通过纠正异常的原因并重试操作。

回滚 Rollback。这种策略允许系统在检测到故障时恢复到先前已知的良好状态,称为“回滚线”,在达到良好状态后,执行可以继续进行。这种策略通常与主动或被动冗余策略结合使用,以便在发生回滚后,恢复组件的备用版本被提升到活动状态。回滚取决于之前的良好状态(检查点)的副本对正在回滚的组件可用。检查点可以存储在固定位置并定期更新,或者在处理中的方便或重要时间(如在完成复杂操作后)进行更新。

软件升级 Software upgrade。软件升级是另一种准备和修复策略,其目标是以不影响服务的方式实现可执行代码映像的在线升级。这可以实现为功能补丁、类补丁或无缝的在线软件升级(ISSU)。功能补丁用于过程式编程,使用增量链接器/加载器将更新的软件

函数存储到目标内存的预分配段中。新版本的软件函数将使用已弃用函数的入口和出口点。此外,在加载新软件函数时,必须更新符号表并使指令高速缓存无效。类补丁策略适用于执行面向对象代码的目标,其中类定义包括启用运行时添加成员数据和函数的后门机制。无缝在线软件升级利用主动冗余或被动冗余策略,实现对软件和相关模式的非影响升级。实际上,功能补丁和类补丁用于交付错误修复,而无缝在线软件升级用于提供新功能和功能。

重试 Retry。重试策略假定导致故障的故障是瞬时的,重试操作可能会成功。这种策略在网络和服务器农场中使用,因为故障是预期的而且很常见。在宣布永久故障之前,应尝试限制重试次数。

忽略故障行为 Ignore faulty behavior。这种策略要求在确定这些消息是虚假消息时忽略从特定来源发送的消息。例如,我们希望通过建立访问控制列表筛选器来忽略来自发起拒绝服务攻击的外部组件的消息。

退化策略 The degradation tactic。退化策略在组件故障的情况下保持最关键的系统功能,而丢弃不太关键的功能。这是在个别组件故障会逐渐降低系统功能而不会导致完全系统故障的情况下执行的。

重新配置 Reconjiguration。重新配置试图通过将责任重新分配给(可能受限的)剩余资源来从组件故障中恢复,同时尽量保持尽可能多的功能。

重新引入 reintroduction tactics 是在已纠正的组件之后重新引入已失败的组件。重新引入策略包括以下内容:

阴影 Shadow。阴影策略指的是在将组件恢复到活动状态之前,在预定义的时间段内以“阴影模式”运行以前失败的或在服务中升级的组件。在此期间,其行为可以进行监视以确保正确性,并可以逐步恢复其状态。

状态重新同步 State resynchronization。状态重新同步是主动冗余和被动冗余准备和修复策略的重新引入伙伴。当与主动冗余策略一起使用时,状态重新同步会自然发生,因为主动和待机组件都会并行接收和处理相同的输入。实际上,定期比较活动和待机组件的状态以确保同步。此比较可以基于循环冗余检查计算(校验和)或者对提供安全关键服务的系统来说,基于周期状态信息从活动组件传输到待机组件,通常通过检查点传输。这种策略的一个特殊情况出现在无状态服务中,其中任何资源都可以处理来自另一个(已失败)资源的请求。

升级重启 Escalating restart。升级重启是一种重新引入策略,允许系统通过改变重新启动的组件的粒度并最小化受影响的服务级别来从故障中恢复。例如,考虑一个支持四个重新启动级别的系统,如下所示。最低级别的重新启动(称为级别0),因此对服务的影响最小,使用被动冗余(温备份),其中杀死并重新创建了故障组件的所有子线程。通过这种方式,只释放和重新初始化与子线程相关的数据。下一个重新启动级别(级别1)释放并重新初始化所有未受保护的内存(受保护的内存将保持不变)。下一个重新启动级别(级别2)释放并重新初始化所有内存,包括受保护和未受保护的内存,迫使所有应用程序重新加载和重新初始化。最后一个重新启动级别(级别3)将涉及完全重新加载和重新初始化可执行映像和相关数据段。对于支持升级重启策略的支持特别有用,因为系统能够在保持对任务关键或安全关键应用程序的支持的同时,降低其提供的服务。

非停止转发(NSF)Non-stop forwarding (NSF)。是一种起源于路由器设计的概念。在此设计中,功能分为两部分:监督或控制平面(管理连接和路由信息)和数据平面(执行路由数据包从发送方到接收方的实际工作)。如果路由器的活动监督员发生故障,它可以在邻近路由器的已知路由上继续转发数据包,同时恢复和验证路由协议信息。当控制平面重新启动时,它实施了所谓的“优雅重启”,即在数据平面继续运行的同时,逐步重建其路由协议数据库。

预防故障

与检测故障然后尝试从中恢复不同,如果您的系统能够预防故障在首次发生呢?虽然这听起来可能需要某种程度的预见性,但事实上,在许多情况下确实可以做到这一点。以下是一些预防故障的策略:

从服务中移除 Removal from service。这种策略指的是暂时将系统组件置于脱机状态,以减轻潜在的系统故障。一个例子涉及将系统的一个组件脱机并重置组件,以便清除潜在故障(例如内存泄漏、碎片化或不受保护高速缓存中的软错误),在故障积累影响服务之前。这种策略的另一个术语是软件复活。

事务 Transactions。面向高可用性服务的系统利用事务语义来确保在分布式组件之间交换的异步消息是原子、一致、隔离和持久的。这四个属性被称为“ACID属性”。事务策略最常见的实现是“两阶段提交”(2PC)协议。这种策略可以防止由两个进程尝试更新相同数据项引起的竞争条件。

预测模型 Predictive model。当与监视器结合使用时,预测模型用于监视系统进程的健康状态,以确保系统在其标称运行参数内运行,并在检测到与可能未来故障相关的条件时采取纠正措施。监视的操作性能指标用于预测故障的发生;示例包括会话建立速率(在HTTP服务器中)、阈值交叉(监视某些受限共享资源的高水位线和低水位线)或维护进程状态的统计信息(在服务中、脱机、维护中、空闲)、消息队列长度统计信息等。

异常预防 Exception prevention。这种策略指的是用于防止系统异常发生的技术。之前已经讨论了使用异常类的情况,它允许系统从系统异常中透明恢复。异常预防的其他示例包括抽象数据类型,例如智能指针,以及使用包装器来防止发生故障,例如悬空指针和信号量访问违规。智能指针通过对指针执行界限检查以及在没有数据引用它时自动释放资源来防止异常。这样可以避免资源泄漏。

扩大能力集 Increase competence set。程序的能力集是它可以正常运行的状态集。例如,大多数除法程序的能力集不包括分母为零的状态。当组件引发异常时,它在发出信号,表示自己已经发现自己超出了其能力集之外,基本上是不知道该怎么办,已经放弃了。扩大组件的能力集意味着将其设计为在正常操作的一部分处理更多的故障情况。例如,假设一个组件假定它可以访问共享资源,如果发现访问被阻止,它可能会引发异常。另一个组件可能只是等待访问,或者立即返回指示下一次在自己拥有访问权限时完成其操作。在这个示例中,第二个组件的能力集比第一个大。

可用性设计清单

表5.4是一个用于支持可用性设计和分析过程的清单。

总结

可用性指的是系统在故障发生后仍然可供使用的能力,故障必须被识别(或预防),然后系统必须以某种方式作出响应。所期望的响应将取决于应用程序的关键性和故障类型,可以从“忽略它”到“继续运行,就像它没有发生一样”。

可用性的策略可分为检测故障、从故障中恢复和预防故障三类。

  • 检测策略基本上依赖于从各个组件中检测到生命迹象
  • 恢复策略是某种操作的重试维护冗余数据或计算的组合
  • 预防策略依赖于从服务中移除元素利用机制来限制故障的范围

所有的可用性策略都涉及到协调模型,因为协调模型必须意识到发生的故障以生成适当的响应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值