嵌入式系统设计人员经常需要实现那些能在99.999%的业务时间内可靠运行的系统,这意味着一天内系统故障的时间将少于一秒。这些系统称为高可用性系统。高可用性系统的设计通过对冗余硬件和软件进行组合,无需人为干预即可管理故障检测和纠错。本文首先简要回顾了与高可用性系统和故障管理相关的一些概念,然后研究了容错系统的一些硬件和软件设计模式。
故障与失效
在设计高可用性系统时,需要重点关注“故障”和“失效”。为了更好地说明,这里将“失效”定义为系统提供的业务与设计规范不符的情况。故障则是与系统相互作用的一种错误,它是人们通常所指的不期望发生事件的可能原因。因此,故障可能是系统的子系统失效、器件失效、外部系统失效或程序错误。
故障可以是瞬时故障、永久故障或周期性故障。故障一旦发生,将导致系统或子系统的状态出错,而这些错误将引发系统失效。故障处理主要有以下四种主要方法:
1. 故障预测;
2. 故障避免;
3. 故障消除;
4. 容错。
故障预测利用数学模型和试验提供故障及其后果的预估。例如,实际中采用的一种故障预测技术就是在系统中插入故障,研究可能出现的各种系统失效。
故障避免和消除则通过严格的系统、硬件和软件开发工艺及正式规范和验证技术加以实现。
容错通过采用各种冗余系统实现,从而避免了故障影响。“失效弱化”是实现容错的一种方法:即便该方法难以提供整体系统性能,也能提供切合实际的部分功能。“失效保护(fail safe)或失效即停(fail stop)”则是另一种容错方法:当故障发生时,该方法在一个安全状态终止系统,而不让系统继续执行。
容错涉及的主要概念是冗余。容错基于这样的思想(或愿望):多个独立的故障不会同时攻击系统。容错系统应能规避单点失效,换言之,如果系统的某部分可能出现故障,那么系统中应当存在解决该故障的冗余部分,从而避免失效。
冗余具有很多种形式:
1. 硬件冗余(低端、高端或两者兼有);
2. 软件冗余;
3. 时间冗余;
4. 信息冗余。
飞机内的自校验逻辑电路及多台飞行计算机即为典型的硬件冗余。软件冗余可采用两种完全不同的算法,得到的结果也完全相同。时间冗余可以利用通信重传实现,而信息冗余则可采用备份、校验及纠错代码实现。
冗余可以是动态的,也可以是静态的,两者均需复制系统的基本要素。在静态冗余中,同一时刻所有的复制要素均保持激活。如果一个复制“抛出”故障,系统能够马上使用另一复制,并继续正确的操作。在动态冗余中,只有一个复制保持激活,而其余复制则不激活。如果被激活的复制产生故障,先前未被激活的一个复制将被激活并接管临界操作。
那么上述各种方法是如何实现高可用性的呢?首先,必须对高可用性进行定义。高可用性表征系统容错并根据规范继续提供业务的能力。系统可以采用本文给出的所有概念和方法实现高可用性。
可用性通常采用“可用度”或“每年故障时间”进行量度。常规的容错系统可以达到99.99%的可靠度,即相当于每年故障1小时(每天故障10秒钟)。但高可用性系统则有望实现高达99.999%的可用度,即每年故障少于5分钟(简单地说,即每天故障1秒钟)。这意味着当故障出现时,系统必须能自动处理,因为操作人员难以在很短的时间内移除或掩盖任何故障。
硬件冗余
与采用极可用器件构建单个极可用模块的硬件设计相比,使用由常规商业级质量的器件构成的常规商业级质量硬件进行冗余复制模块设计,无疑具有更高的成本效益。
每个复制通常都要求具有“快速失效”或“失效即停”特性,这极大地简化了故障管理决策。每次失效都使硬件在运行中停止,而不是试图勉强执行下去并要求管理人员指出模块中哪些输出发生故障,哪些则一切正常。
对于采用静态冗余的容错,每个复制模块都具有常规的商用可用性。采用双重复制的模式称为配对或双路复用(duplexing)。如果采用了N个复制,则称为N路复用(N-plexing)。
图1显示了3路复用或3重冗余硬件设计,这三重复制均位于方框图的底端附近。这些复制向“表决器”提交输出,表决器决定了子系统的最终实际输出。在N路复用设计中,当N ≥ 3时,表决器通常采用多数决策策略。但是,这需要占不失效复制的绝大多数,而不仅仅是占复制总数(失效和不失效复制)的简单多数。
然而,表决器的硬件和软件不是类似于系统中的任何其他模块,也会失效吗?实际上,确实如此;而且一旦失效,还会给系统带来灾难性的影响。但表决器通常极为简单,因此可以通过设计和测试保证其鲁棒性。此外,还可以设计复杂表决器和二级表决器等复杂系统,但本文不准备进行深入讨论。
对于采用动态冗余的容错,复制模块仍然只需具有常规的商用可用性。一种实现方法是采用由一个被激活模块和一个备用模块组成的冗余对。另一方法则采用一簇模块,这些模块不必是其他模块的精确复制,可以具有不同的特征、接口和容量。这簇复制需要采用失效接替策略,这样当主模块出现故障时,就能确定如何对多个模块进行管理。下面给出了一些选择:
1. 热备用。主模块在系统中运行时,备份模块处于“热备用”状态,一旦主模块出现故障,备份模块将启动并接管主模块。例如,可以采用这种方法设计高可用性的互联网服务器。
2. 转动备用。主模块在系统运行时,可以具有许多备用模块。一旦主模块出现故障,一个备用模块将接管系统的运行。航天飞机上飞行计算机的设计就基于该原理:主模块由两台总稳定工作的计算机组成,其中一个备用模块是一个相似对(similar pair),而第二个备用模块则是一台只能根据操作员指令接管系统的计算机。
3. 非关键模块的失效接替。主模块占用系统的关键资源,备用模块则占用其他非关键资源。一旦主模块出现故障,备用模块就能接管主模块占用的大部分关键资源。日常生活中我们也常常这么做:当我们试图发送一封紧急的电子邮件时,如果计算机的高速互联网连接出现故障,我们会立即切换到旧式的调制解调器。
4. 共同接管。每个模块均运行自带的关键资源,而且一旦某个模块发生故障,其他模块还能接管故障模块的关键资源。例如,在功能增强的心护理室中,每8位病人将设置一台心脏监控计算机。如果一台心脏监控计算机崩溃,那么邻近的计算机也能对故障计算机监控的8位病人进行监控(或许性能将有所降低)。
正确的失效接替实现非常关键。如果故障的主模块需要抛弃故障并继续执行,而同时另一模块也试图接管其业务,那么后果将是灾难性的,因为它们的业务有可能产生冲突。如果主模块抛弃故障后停止执行,而又没有其他模块接管其业务,这样的后果同样是灾难性的。因此失效接替的验证和测试非常关键,尽管我们当中的许多人并不热衷于此。
软件冗余
大多数硬件故障都是随机产生并由物理缺陷导致,这些缺陷要么在生产过程中维持不变,要么随器件的老化而不断变化,要么将受到外部物理环境的冲击。相反,软件故障与物理条件无关,因为软件不会老化。与硬件故障不同,软件故障源自对软件设计或实现中固有故障的软件路径调用。由于软件通常比硬件复杂,因此软件中可能具有比硬件多得多的内置缺陷,从而导致软件中的故障更多,容错设计的成本也更高。
N版编程(N-version programming )是久经考验的一种软件容错设计方法。20世纪70年代偶然接触到该方法时,那时还被称为异质软件(dissimilar software)。这是硬件N路复用(如图1所示)的等价软件实现。但该方法比硬件N路复用的复制机制复杂,N路复用中相同软件的N个复制将包含相同的故障并产生N次相同的错误。在N版编程中,如果N套软件功能需要并行运行,那么它们应当是该功能的N个不同实现,而且是由N个单独的开发团队独立开发完成。这就是N版编程的基本原理。
1996年6月,当首次发射的阿丽安娜-5卫星发送火箭上升到4000米高空时,突然发生了爆炸。该事故的原因在于火箭的惯性参考系统(这是数字飞行控制的一部分)发生了故障。尽管惯性参考系统中引入了硬件冗余,但软件冗余没有得到正确的处理。阿丽安娜-5带有两台惯性参考计算机,一台处于工作状态,而另一台则处于“开机”备用状态。这两套系统并行运行,并具有完全一样的硬件和软件。系统上的软件也与先前已经成功发射的阿丽安娜-4几乎一模一样,但由于阿丽安娜-5上的某些飞行参数值比阿丽安娜-4大,因此数据发生了溢出。解决问题的方法是关闭计算机,由于冗余计算机也在运行相同的软件,因此也将受到数据溢出的冲击,从而很快关闭,这样整个惯性参考系统就完全崩溃。结果,引擎的喷管被回旋至极限位置,导致火箭突然转向,并在自毁之前裂成两半。这种处理数据溢出错误的方法适用于处理随机出现的硬件错误,但不适用于处理两台计算机上出现的类似软件错误。N版编程可以避免两台计算机出现类似的软件错误。
在20世纪70年代,N版编程(N-version programming)是先进的软件容错设计方法。此后,这种设计模式引发了一系列问题:随着该技术的采用,软件开发成本直线飙升,因为必须成立N个单独的团队开发N套相互独立的软件。如果期望降低成本,则将陷入所谓的“平均智商( Average IQ)”怪圈:较低成本的开发团队意味着较低质量的软件工程师,而这些工程师只能开发出较低质量的代码。因此,最终只能得到充斥着以N种不同方式产生故障的N种不同程序。
[page]
N版编程面临的另一个问题在于如何为N个独立开发团队提供输入。一般情况下,将为所有的N个开发团队提供相同的规范标准。然而,一旦规范存在缺陷,那么将得到N个独立开发的包含类似软件故障的版本。如果系统发布之后,规范或使用错误得到识别,那么每个新错误都需要纠正N次,即N个不同的实现都需要加以纠正,这样维护成本就相当惊人。现在,最佳的N版编程方法是让第一流的软件开发团队,利用最可靠的底层架构、软件开发工具、技术和测试来开发出高质量的软件版本。
校验点恢复
与基于静态冗余的N版编程不同,许多软件容错设计模式均基于动态冗余。这些设计模式均包含以下四个步骤:
1. 故障检测
2. 损害评估与 限制(有时也称为“防火墙处理”)
3. 故障恢复
4. 故障处理和业务继续
步骤二中,当检测到软件错误时,一般可以采用失效保护。但软件往往极其复杂,因此消除故障软件导致的后果也并非轻而易举。事务的概念是解决该问题的一个有效工具,事务是应用状态下操作的集合,这样事务的起始点和结束点均是应用的稳定状态。例如,每个城市的市政厅都具有一个包含该城市所有居民信息的文件系统。当一对夫妻结婚时,他们的姓名和结婚日期都记录在一个命名为“已婚夫妻”的文件中。另外,记载新郎从单身到已婚状态变化的文件称为“男性居民”;记载新娘从单身到已婚状态变化的文件称为“女性居民”。如果上述3个文件中的一个未能得到有效更新或者软件在更新过程中突然崩溃,我们将不得不返回到该婚姻“事务”的起始点。否则,将只会以不稳定状态而告终,如新郎显示为已婚状态,而新娘则仍然显示为单身状态。稳定状态只出现在婚姻事务的起始点以及得到成功处理的结束点。
如果希望在容错中引入事务概念,系统必须能在事务的起始点保存系统状态,这称为检验指示。检验指示需要在开始新事务之前迅速保存系统状态,并且必须要求先前的事务以无差错状态结束。这里,一种基本的恢复策略是再执行方法:一旦事务中检测到错误,事务将进行失效保护,系统将重新载入最近保存的检验点。这样业务又能从检验点继续执行下去,并允许在该稳定状态上进行新的事务处理。然而,这样将丢失进行失效保护的事务。这类故障恢复也称为后向故障恢复,因为软件状态将还原到先前的一个无差错点上。
简单的检验指示本身也容易引发单点失效,因为在保存检验点状态时有可能出现故障,但我们可以采用一种称为检验点还原(checkpoint-rollback)的方法解决这个问题,如图2所示。图中,椭圆符号代表通过发送队列消息进行通信的软件客户和软件服务器。一个事务可以包含许多从客户机发往服务器的请求消息以及从服务器发往客户机的响应消息。在一个事务中,数据在服务器中修改。在事务的结束点,右图所示的两个恒定大容量存储设备将记录稳定的数据集和事务序列号。如果某一时刻检测到错误,而服务器已被关闭,那么服务器将重启(或启动备用服务器)。作为启动恢复过程的一部分,两个大容量存储设备还需要检验事务序列号。服务器数据将根据包含最高序列号的设备进行恢复。因为故障出现在设备检验中,因此另一大容量设备将带有较低的序列号。
流程对设计模式
检验点设计模式的一个缺陷在于故障恢复时间过长。启动或重启服务器需要进行许多处理,才能恢复到检验点状态。“热备用”服务器与其自带的恒定大容量存储设备的直接协同工作可以加速恢复,该设计模式也称为流程对(process pair)设计,如图3所示。
图3中,方框图中央是一个工作原理与先前检验点情形非常相似的主服务器,客户机直接与主服务器协同工作。一旦主服务器成功地完成整个事务,将传送与新的稳定状态相关的信息至备用服务器(右端的服务器)。主服务器和备用服务器都将在恒定大容量设备中记录数据。这样,备用服务器就能保存完整事务的当前信息。当主服务器准备就绪并可供客户机使用,将向备用服务器发送常规的“心跳消息(heartbeat message)”,这些心跳消息还可以同某些检验点消息相结合。一旦检测到心跳消息流终止,备用服务器就知道主服务器已关闭或无法使用,进而作为一个新的主服务器迅速接管事务。
该设计模式不仅适用于客户机、主服务器和备用服务器均位于同一处理器或模块上的情形,还适用于三者位于不同处理器或模块的情形。
尽管流程对设计模式具有诸多优势,但仍有一些问题需要解决。例如,备用服务器丢失了检验点消息或消息的顺序不对,而且,当主服务器是物理设备的控制器并在操作中发生故障时,也会产生问题。当备用服务器接管事务时,不必知道如何完成操作,因为备用服务器并不知道主服务器失效之前究竟运行到哪一步。
需要再次重申的是,在流程对设计模式中,当主服务器失效时,仍在进行的事务将在执行中丢失或撤销。备份服务器接管主服务器的状态是主服务器失效前报告给备用服务器最后完成的事务的状态。
恢复程序块
动态软件冗余的另一种设计模式称为恢复程序块。该方法基于检验指示,但添加了对软件处理结果的验收测试。设计中必须准备数据处理的替代方法(就像在N版编程中一样),但不必对每个事务运行所有的数据处理方法。相反,可以选择一种数据处理方式作为主方式,并且首先只采用主方式处理事务。一旦主处理完成,即可运行验收测试。如果验收测试通过,则表明主数据处理方式完全有效。如果验收测试失败,则可如图4所示,继续试验下一个替代方案。
如方框图所示,必须在首次进入恢复程序块之前进行检验指示。每次失效的验收测试之后,软件必须还原到检验点状态。每次尝试替代的处理方法之后,都必须进行验收测试。这样,需要不断进行处理方式更迭,直到提供通过验收测试的处理方式。这些“良好”的输出构成了恢复程序块的最终结果。
前向故障恢复
检验点恢复、流程对和恢复程序块都是后向故障恢复方法。大多数动态软件容错都采用后向故障恢复方法,但前向故障恢复也是不错的选择。前向故障恢复的基本思想是从错误状态继续进行并通过校正清除故障。前向故障恢复基于精确的错误损失评估,因此通常取决于具体的系统。异常处理就是前向故障恢复的一个典型例子,当检测到问题,该方法就发送命令至专用的异常处理软件,而不是返回到先前某个检验点状态并继续执行下去。
替代处理是前向故障恢复的一种设计模式。当某个事务存在两种(或更多)处理选择时,就可以采用替代处理方法。在这两种处理方法中,一种方法非常精确,但计算复杂;另一种方法则相对简单并具有更高的性能。替代方法不仅可用作测试,而且当主处理方法出现故障时也可用作二级结果提供器。例如,平方根算法可作为主处理方法,而表查询插入算法则可作为替代方法。一旦运行了平方根算法,表查询插入算法不仅可用于测试平方根算法所得结果的质量,还能迅速校正这些结果中的错误。
图5中,为了控制飞机(波音777),同时采用了两套数字飞行数字系统。框图右侧的决策逻辑电路将简单飞行控制系统的输出作为测试复杂的主飞行控制系统输出的衡量标准。如果验收测试失效,简单飞行控制系统的输出也可用作失效主输出的替代,向左的箭头表示替代处理的结果也可为主处理提供反馈。
上述设计模式使采用常规商业级质量的硬件和软件为真正的高可用性系统构造程序块成为可能,这样的高性能系统无需人为干预,即可实现高达99.999%或更高的可靠性。
上一篇:基于AVR单片机的温度测量系统
下一篇:在数据采集应用中怎样选择合适的采样率
推荐阅读最新更新时间:2024-03-30 22:07