软件系统三大关切之可靠性Reliability(软件系统可靠性分析)

系统应该持续正确的工作,或者说在希望的性能水平下执行正确的功能,即使出现一些困难,比方说硬件或软件错误,甚至人为错误。

对于某样东西的是否可靠意味着什么,每个人都有一个直观的想法。对于软件来说,普遍的期望包含:

  • 应用程序执行用户所希望的功能
  • 它可以容忍用户以一种不可预见的方式使用软件或犯错。
  • 在期望的负载和数据体量下,对于要求的用例的执行性能足够好
  • 系统能防止任何未经授权的访问和滥用。

如果把这些所有的包含在一起就说是“正确的工作”,那么我们大致可以这样理解可靠性:

即使当有东西出错了,也能继续正确的工作

出错的东西称为故障faults,能够预料故障并且能够处理地的系统叫做容错fault-tolerant系统或弹性resilient系统。前者可能有一些轻微的误导:它指的是我们可以制造出一个系统容忍所有可能的故障,这在现实中是不可行的。比方说,整个地球(所有的服务器都在上面)被一个黑洞吞噬了,那么为么实现这一容错,那么就会要求把服务器全部放在宇宙中,如果预算能得到通过的话,那还是不错的。所以说我们只谈论容忍某种类别certain types的错才有意义。

请注意,fault指的故障和failure指的故障是不同的。fault通常系统的一个组建的与它的说明规格相偏离,而failure指的是整个系统停止为用户提供所需的服务。把fault发生的概率降到零是不可能的,因此通常最好是设计容错机制以防止faults导致failures。

但令人往往想不到的是,在这样的容错机制的系统中,通过故意触发而提高故障率是有意义的。比方说,在没有警告的情况下随机杀死一个单独的进程。许多致命的bugs其实是因为不佳的错误处理方式而造成的。通过故意诱导一些故障,你可以确保容错机制是在持续接受实际检验和测试的。这也能增强,当这些故障自然而然的发生时,故障能被正确处理的信心。

虽然我们比起预防故障更偏爱与容忍故障,但也有一些例子展示了预防胜于治疗(因为无法治疗)。安全问题就是这种情况:如果攻击者破坏了系统,并且获取了对敏感信息的权限。这个事件就无法撤销。

硬件故障

当我们考虑系统故障failure的原因时,硬件故障很快出现在我们的脑海中。硬盘会崩溃,RAM会出错,电网会停电,某些人拔掉了错误的网线。任何工作在大型数据中心的人会告诉你,当你有许多机器时,这些事会一直发生。

硬盘的平均失效时间(mean time to failure,MTTF)是大约10到50年之间。因此,在具有10,000个磁盘的存储群集上,我们应该可以想象的到平均每天会有一块硬盘说拜拜。

为了降低系统的故障faliure率,我们首先想到的是增加单个硬件组件的冗余性:

  • 硬盘可以配置成磁盘阵列(Redundant Arrays of Independent Disks,RAID
  • 服务器可以有双电源以及可热拔插的CPU
  • 数据中心可以有电池和柴油发电机作为备用电源

那么当一个组件拜拜后,冗余组件就可以替换失效的组件继续工作。这些方法不能完全预防硬件问题的导致的failures,但很容易被理解并且通常能保持一台机器不受打扰的运行好几年。

直到现在,因为造成单个机器完全failure的事件很少或几乎没有,冗余的硬件组件对于大多数应用来说是足够了。只要你能在一台新的机器上相当快速的恢复备份,发生failure的停机时间对于大多数应用来说都不是灾难性的。因此,对于少数高可用性应用程序所需的多级冗余绝对是必要的。

然而,随着数据体量金额应用计算需求的不断提升,更多的应用开始使用更大数量的机器,这也同比提升了硬件的故障率。此外,在一些云平台,比方说AWS,由于平台旨在优先考虑灵活性和弹性,而不是单机可靠性,对于虚拟机来说没有任何警告的突然不可用是很平常的。

因此,人们开始朝着除了硬件冗余之外,通过优先使用软件容错技术来使系统能够容忍一整台机器丢失的故障。这样的系统还具有操作运营的优势:如果需要重启机器(比如添加操作系统的安全补丁),单台服务器需要计划停机时间,在这样的情况下,这样系统可以容忍一次一台机器因为打补丁而造成的failure,而不会使整个系统停机。

软件错误

我们通常任务硬件故障是随机的并且独立于其他的(一台机器硬盘的失效不意味着另一台机器的硬盘也要坏了)。虽然可能存在弱相关性,比方说,由于一些通常的原因诸如服务器机架里的温度,但一般不可能存在同一时间大量的硬件组件的失效。

另一类的故障是系统内的系统故障。这样的故障是很难被预料到的,因为它们在节点之间是相互关联的,所以它们往往会导致比不相关的硬件故障多得多的系统failure。这样的例子有:

  • 在给定特殊输入错误的情况下,导致应用程序服务器的每个实例崩溃的软件错误。例如,2012年6月30日的闰秒(leap second),由于Linux kerne中的错误,导致许多应用程序同时挂起.
  • 一个跑飞了的进程,耗光了一些共享资源(CPU时间,内存,磁盘空间或网络贷款)
  • 系统依赖的服务速度降低,变得无响应或开始返回被破坏了的的响应。
  • 级联故障,其中一个组件中的小故障会触发另一个组件的故障,或开始引发更多故障。

造成这些类别的软件故障的错误长时间处于休眠状态直到它们被异常情况触发。在这样的情况下,可以发现软件对其运行环境作出了某种假设,虽然这种假设通常都对,但最终会因为某些原因而变得不对。

没有快速的方法去解决软件中的系统错误。但有许多小事情可以帮到你:

  • 仔细考虑系统中的假设以及相互作用
  • 全面测试
  • 进程隔离
  • 允许进程崩溃并重新启动
  • 测量,检测和分析生产环境中的系统行为

如果希望系统提供某种保证,例如,消息队列的传入数量等于传出数量,那么它自己就要运行时自我检测,并且发现差异时发出警报。

人为错误

人们设计和建造软件系统,并且维持系统运行的操作者也是人。即使他们的出发点都是好的,但众所周知的是,人就是不可靠的。例如,一项有关大型互联网服务的研究发现操作员的配置错误是服务中断的主要原因,而硬硬件故障(服务器或网络)仅占服务中断的10–25%。

尽管人类不可靠,那么我们如何使我们的系统可靠?最好的系统结合了以下几种方法:

  • 以最小化出错机会的方式设计系统。例如,精心设计的抽象,API和管理界面可轻松实现“正确的事情”,阻止“错误的事情”。但是,如果接口太有限制性,那么围绕接口工作的人就会否定因限制而带来的好处,所以权衡这些就会变得很棘手。
  • 将人们最容易犯错的地方与会导致failures故障的地方分开。特别的是,可以提供功能齐全的非生产沙盒环境,人们可以使用真实数据去安全地探究和实验,而不影响真实用户。
  • 从单元测试到整个系统集成测试和手动测试,在各个级别上进行全面测试。自动化测试已经被广泛使用,并且对覆盖在正常操作中很少出现的极端情况特别有价值。
  • 可以快速,轻松地从人为错误中恢复,以最大程度地减少发生故障时的影响。例如,快速回滚配置更改,逐步推出新代码(以便所有意外错误仅影响一小部分用户),并提供重新计算数据的工具(以防万一发现原来的计算不正确) 。
  • 设置详细而清晰的监视,例如性能指标和错误率。在其他工程学科中,这称为遥测。(一旦火箭离开地面,遥测对于跟踪正在发生的事情以及理解故障是必不可少的。)监视可以向我们显示预警信号,并允许我们检查是否违反了任何假设或约束。发生问题时,度量标准对于诊断问题非常重要。
  • 实施良好的管理规范和培训

可靠性有多重要?

可靠性不只是为了核电站以及空中交通控制软件,普通应用程序也应该被期望是可靠地工作的。业务应用程序中的错误会导致生产力下降(如果数字报告不正确,则会导致法律风险),并且电子商务网站的中断可能会在收入和声誉方面带来巨大的损失。

即使在“非关键”应用程序中,我们也要对用户负责。设想一个将孩子的所有图片和视频存储在您的照片应用程序中的父母。如果该数据库突然损坏,他们会有什么感觉?他们知道如何从备份中还原吗?

在某些情况下,我们可能会选择牺牲可靠性以降低开发成本(例如,为未经验证的市场开发原型产品时)或运营成本(例如,对于利润率非常窄的服务),但是,当我们偷工减料时,我们应该要非常清楚的意识到这一点。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(1)
上一篇 2023年3月16日 上午9:29
下一篇 2023年3月16日 上午9:45

相关推荐