\公众What Would You Do If You Weren't Afraid?\"大众 和 \"大众Fortune Favors the Bold.\公众 是 FB 公司信条,挂墙上那种。
为了能在快速变更的系统中使 FB 的系统稳定,工程师们对系统故障进行了一些总结和抽象,为了能够建立可靠的系统必须要理解故障。而为了理解故障,工程师们建立了一些工具来诊断问题,并建立了对事件进行复盘,以避免未来再次发生的文化。
事件的发生可以被分为三大类。

常日情形下,单机遇到的伶仃故障不会影响到根本举动步伐的其他部分。这里的单机故障指的是:一台机器的硬盘涌现了故障,或者某台机器上的做事碰着了代码中的缺点,如内存破坏或去世锁。
避免单个机器故障的关键是自动化。通过总结已知的故障模式,并与探究未知的故障症状相结合。在创造未知故障的症状(如相应缓慢)时,将机器摘除,线下剖析,并将其总结至已知故障中。
事情负载变革现实天下的重大事宜会对 Facebook 网站根本举动步伐带来压力,比如:
这些事宜中网络到的统计数据会为系统设计供应独特的视角。重大事宜会导致用户行为变革,这些变革能为系统后续的决策供应数据依据。
人为缺点图 1a 显示了周六和周日发生的事件是如何大幅减少的,只管网站的流量在全体一周内保持同等。图 1b 显示了在六个月的韶光里,只有两个星期没有发生事件:圣诞节的那一周和员工要为对方写同行评论的那一周。
上图解释大部分故障都是人为缘故原由,由于事宜的统计与人的活动规律是同等的。
故障的三个缘故原由故障的缘故原由很多,不过有三种最为常见。这里列出的每一种都给出了预防方法。
快速支配的配置变更配置系统每每被设计为在环球范围内快速复制变革。快速配置变更是 强大的工具,然而,快速配置变更可能导致支配问题配置时发生事件。下面是一些防止配置变更故障的手段。
所有人公用同一套配置系统。利用一个共同的配置系统可以确保程序和工具适用于所有类型的配置。
配置变革静态检讨。许多配置系统许可疏松类型的配置,如 JSON 构造。这些类型的配置使工程师很随意马虎打错字段的名称,在须要利用整数的地方利用字符串,或犯其他大略的缺点。这类大略的缺点最好用静态验证来捕捉。构造化格式(Facebook 利用 Thrift)可以供应最基本的验证。然而,编写程序来对配置进行更详细的业务层面的验证也是该当的。
金丝雀支配。将配置先支配到小范围,防止变更造成灾害性后果。金丝雀可以有多种形式。最大略的是 A/B 测试,如只对 1% 的用户启用新的配置。多个 A/B 测试可以同时进行,可以利用一段韶光的数据来跟踪指标。
就可靠性而言,A/B 测试并不能知足所有需求。
为了避免配置导致的明显问题,Facebook 的根本举动步伐会自动在一小部分做事器上测试新版本的配置。
例如,如果我们希望向 1% 的用户支配一个新的 A/B 测试,会首先向 1% 的用户支配测试,担保这些用户的要求落在少量做事器上,并对这些做事器进行短韶光的监控,以确保不会由于配置更新涌现非常明显的崩溃问题。
坚持可以运行的配置。配置系统设计方案担保在发生失落败时,保留原有的配置。开拓职员一样平常方向于配置发生问题时系统直接崩溃,不过 Facebook 的根本举动步伐开拓职员认为用老的配置,使模块能运行比向用户返回缺点好得多。(注:我只能说这个真的要看场景)
配置有问题时回滚要快速。有时,只管尽了最大努力,有问题的配置还是上了线。迅速回滚是办理这类问题的关键。配置内容在版本管理系统中进行管理,担保能够回滚。
强依赖核心做事开拓职员方向于认为,核心做事:如配置管理、做事创造或存储系统,永久不会失落败。在这种假设下,这些核心做事的短暂故障,会变成大规模故障。
缓存核心做事的数据。可以在做事本地缓存一部分数据,这样可以降落对缓存做事的依赖。 供应专门 SDK 来利用核心做事。 核心做事最好供应专门的 SDK,这样担保大家在利用核心做事时都能遵照相同的最佳实践。同时在 SDK 中可以考虑好缓存管理和故障处理,利用户一劳永逸。 进行演习训练。 只要不进行演习训练,就没法知道如果依赖的做事挂了自己是不是真的会挂,以是通过演习训练来进行故障注入是必须的。
延迟增加和资源耗尽有些故障会导致延迟增加,这个影响可以很小(例如,导致 CPU 利用量微微增加),也可以很大(做事相应的线程去世锁)。
少量的额外延迟可以由 Facebook 的根本举动步伐轻松处理,但大量的延迟会导致级联故障。险些所有的做事都有一个未处理要求数量的限定。这个限定可能是由于要求相应类做事的线程数量有限,也可能是由于基于事宜的做事内存有限。如果一个做事碰着大量的额外延迟,那么调用它的做事将耗尽它的资源。这种故障会层层传播,造成大故障。
资源耗尽是特殊具有毁坏性的故障模式,它会使要求子集所利用的做事的故障引起所有要求的故障:
一个做事调用一个新的实验性做事,该做事只向 1% 的用户推出。常日情形下,对这个实验性做事的要求须要 1 毫秒,但由于新做事的失落败,要求须要 1 秒。利用这个新做事的 1% 的用户的要求可能会花费很多线程,以至于其他 99% 的用户的要求都无法被实行。
下面的手段可以避免要求堆积:
注:虽然里面写着 M 和 N,但实在 M 和 N 是定值,N = 100ms,M = 5ms
onNewRequest(req, queue):if queue.lastEmptyTime() < (now - N seconds) { timeout = M ms } else { timeout = N seconds; } queue.enqueue(req, timeout)
在这个算法中,如果行列步队在过去的 100ms 内没有被清空,那么在行列步队中花费的韶光被限定在 5ms。如果做事在过去的 100ms 能够清空行列步队,那么在行列步队中花费的韶光被限定为 100 ms。这种算法可以减少排队(由于 lastEmptyTime 是在迢遥的过去,导致 5ms 的排队超时),同时许可短韶光的排队以达到可靠性的目的。虽然让要求有这么短的超时彷佛有悖常理,但这个过程许可要求被快速丢弃,而不是在系统无法跟上传入要求的速率时堆积起来。较短的超时时间可以确保做事器接管的事情总是比它实际能处理的多一点,以是它永久不会闲置。
前面也说了,这里的 M 和 N 基本上不须要按场景调度。其他办理排队问题的方法,如对行列步队中的项目数量设置限定或为行列步队设置超时,须要按场景做 tuning。M 固定 5 毫秒,N 值为 100 毫秒,在大多场景下都能很好地事情。Facebook 的开源 Wangle 库和 Thrift 利用了这种算法。
只管有最好的预防方法,故障还是会发生。故障期间,利用精确的工具可以迅速找到根本缘故原由,最大限度地减少故障的持续韶光。
利用 Cubism 的高密度仪表板在处理事件时,快速获取信息很主要。好的仪表盘可以让工程师快速评估可能涌现非常的指标类型,然后利用这些信息来推测根本缘故原由。然而仪表盘会越来越大,直到难以快速浏览,这些仪表盘上显示的图表有太多线条,无法一览无余,如图3所示。
为理解决这个问题,我们利用 Cubism 构建了我们的顶级仪表盘,这是一个用于创建地平线图表的框架--该图表利用颜色对信息进行更密集的编码,许可对多个类似的数据曲线进行轻松比较。例如,我们利用 Cubism 来比较不同数据中央的指标。我们环绕 Cubism 的工具许可大略的键盘导航,工程师可以快速查看多个指标。图 4 显示了利用面积图和水平线图的不同高度的同一数据集。在面积图版本中,30像素高的版本很难阅读。同一高度下地平线图非常随意马虎找到峰值。
最近发生了什么变更?
由于失落败的紧张缘故原由之一是人为缺点,调试失落败的最有效方法之一是探求人类最近的变革。我们在一个叫做 OpsStream 的工具中网络关于最近的变革的信息,从配置变革到新版本的支配。然而,我们创造随着韶光的推移,这个数据源已经变得非常喧华。由于数以千计的工程师在进行改变,在一个事宜中每每有太多的改变须要评估。
为理解决这个问题,我们的工具试图将故障与其干系的变革联系起来。例如,当一个非常被抛出时,除了输出堆栈跟踪外,我们还输出该要求所读取的任何配置的值最近发生的变革。常日,产生许多缺点堆栈的问题的缘故原由便是这些配置值之一。然后,我们可以迅速地对这个问题做出反应。例如,让上线该配置的工程师赶紧回滚配置。
从失落败中学习失落败发生后,我们的事宜审查过程有助于我们从这些事宜中学习。
事宜审查过程的目的不是为了责怪。没有人由于他或她造成的事宜被审查而被开除。审查的目的是为了理解发生了什么,补救使事宜发生的情形,并建立安全机制以减少未来事宜的影响。
审查事宜的方法 Facebook 发明了一种名为 DERP(detection, escalation, remediation, and prevention)的方法,以帮助进行富有成效的事宜审查。
检测 detection。如何检测问题--报警、仪表板、用户报告?
升级 escalation。精确的人是否迅速参与?这些人是否可以通过警报被拉进故障处理流程,而不是人为拉进来?
补救 remediation。采纳了哪些步骤来办理这个问题?这些步骤是否可以自动化?
预防 prevention。哪些改进可以避免同类型的故障再次发生?你如何能优雅地失落败,或更快地失落败,以减少这次故障的影响?
在这种模式的帮助下,纵然不能防止同类型的事宜再次发生,也至少能够不才一次更快规复。
一把梭的时候少出故障\公众move fast\"大众 的心态不一定与可靠性冲突。为了使这些理念兼容,Facebook 的根本举动步伐供应了安全阀:
为了处理漏网之鱼,还建立了易于利用的仪表盘和工具,以帮助找到与故障关联的最近的变更。
最主要的是,在事宜发生后,通过复盘学到的履历将使根本举动步伐更加可靠。
ReferencesCoDel (controlled delay) algorithm; http://queue.acm.org/detail.cfm?id=2209336.
Cubism; https://square.github.io/cubism/.
HipHop Virtual Machine (HHVM); https://github.com/facebook/hhvm/blob/43c20856239cedf842b2560fd768038f52b501db/hphp/util/job-queue.h#L75.
Thrift framework; https://github.com/facebook/fbthrift.
Wangle library; https://github.com/facebook/wangle/blob/master/wangle/concurrent/Codel.cpp.
https://github.com/facebook/folly/blob/bd600cd4e88f664f285489c76b6ad835d8367cd2/folly/executors/Codel.cpp