失败是任何大型系统工程的一部分。Facebook的文化价值观之一就是拥抱失败。这一点可以从我们门洛帕克总部墙上挂着的海报上看出来:“如果你无所畏惧,你会做什么?”和“命运偏爱勇敢者”。
为了保持Facebook在面对快速变化时的可靠性,我们研究了失败中的常见模式,并构建了解决它们的抽象方法。这些抽象确保了最佳实践应用于我们的整个基础设施。为了指导我们构建可靠性抽象的工作,我们必须理解我们的失败。为此,我们建立了诊断问题的工具,并建立了一种回顾事件的文化,促使我们做出改进,以防止未来的故障。
虽然每一次失败都有一个独特的故事,但许多失败都可以归结为少数几个根本原因。
个人机故障.通常,一台单独的机器会遇到孤立的故障,而这不会影响到基础设施的其余部分。例如,可能一台机器的硬盘驱动器失败了,或者某个特定机器上的服务在代码中出现了错误,比如内存损坏或死锁。
避免个别机器故障的关键是自动化。自动化的最佳工作方式是将已知的故障模式(例如有s.m.a.r.t错误的硬盘驱动器)与搜索未知问题的症状(例如,更换响应时间异常缓慢的服务器)结合起来。当自动化发现未知问题的症状时,手动调查可以帮助开发更好的工具来检测和修复未来的问题。
合法的工作负载的变化.有时Facebook用户的行为改变会给我们的基础设施带来挑战。例如,在世界重大事件期间,特定类型的工作负载可能会以不同寻常的方式给我们的基础设施带来压力。当奥巴马赢得2008年美国总统大选时,他的Facebook主页的活跃度创下了历史新高。在像超级碗或世界杯这样的大型体育赛事中,高潮的发挥会产生非常多的位置。负载测试,包括“暗启动”(功能被激活但对用户不可见),有助于确保新功能能够处理负载。
在这些事件中收集的统计数据通常为系统设计提供了一个独特的视角。通常,重大事件会导致用户行为的改变(例如,围绕特定对象创建集中活动)。关于这些变化的数据通常指向设计决策,允许在后续事件中更平稳地操作。
人为错误.鉴于Facebook鼓励工程师“快速行动,打破陈情”,这是办公室里的另一个装饰海报,人们可能会认为许多错误是由人类造成的。我们的数据表明,人为错误是我们失败的一个因素。图1包括来自对严重到足以被视为违反服务水平协议(SLA)的事件时间的分析的数据。每一个违规都表明我们的内部可靠性目标没有达到,并导致产生警报。因为我们的目标是严格的,大多数这些事件都是轻微的,不会被网站的用户注意到。图1a显示,尽管网站的流量在一周内保持不变,但周六和周日发生的事件大幅减少。图1b显示了六个月的时间里,只有两周没有发生事故:圣诞节的那周和员工被要求写同事评议的那周。
这两个数据点似乎表明,当Facebook的员工因为忙于其他事情(周末、假期或甚至绩效评估)而不积极地对基础设施进行更改时,网站的可靠性水平会更高。我们相信,这不是做出改变的人的疏忽造成的结果,而是证明我们的基础设施在面对机器故障等非人为原因的错误时,在很大程度上能够自我修复。
虽然失败有不同的根本原因,但我们发现了三种放大失败并导致它们广泛传播的常见病理。针对每种病理,我们都制定了预防措施,以减轻广泛的失败。
快速部署的配置更改.配置系统往往被设计成在全局范围内快速复制更改。快速配置更改是一个强大的工具,可以让工程师快速管理新产品的发布或调整设置。但是,当部署了错误的配置时,快速的配置更改意味着快速的失败。我们使用许多实践来防止配置更改导致失败。
然而,为了可靠性的目的,A/B测试并不能满足我们所有的需求。部署到少量用户的更改,但导致相关服务器崩溃或耗尽内存,显然会产生超出测试中有限用户的影响。A/B测试也很耗时。工程师通常希望在不使用A/B测试的情况下推出较小的更改。由于这个原因,Facebook基础设施会在一小组服务器上自动测试新配置。例如,如果我们希望向1%的用户部署一个新的a /B测试,我们将首先将测试部署到1%的访问少量服务器的用户。我们会在短时间内监视这些服务器,以确保它们不会崩溃或出现其他明显的问题。该机制对所有更改提供基本的“健全检查”,以确保它们不会导致广泛的失败。
对核心服务的硬依赖.开发人员倾向于假设核心服务,如配置管理、服务发现或存储系统永远不会失败。然而,即使是这些核心服务中的短暂故障也可能演变成大规模事件。
延迟增加,资源耗尽.有些失败会导致服务对客户端的延迟增加。延迟的增加可能很小(例如,考虑人为配置错误导致CPU使用量增加,但仍然在服务的能力范围内),也可能几乎是无限的(服务响应的线程已经死锁)。虽然少量的额外延迟可以由Facebook的基础设施轻松处理,但大量的延迟会导致级联故障。几乎所有的服务都有未完成请求数量的限制。这种限制可能是由于每个请求线程的服务中的线程数量有限,也可能是由于基于事件的服务中的内存有限。如果一个服务经历了大量的额外延迟,那么调用它的服务将耗尽它们的资源。这种故障可以通过多个服务层传播,导致广泛的故障。
为了指导我们构建可靠性抽象的工作,我们必须理解我们的失败。为此,我们建立了诊断问题的工具,并建立了一种回顾事件的文化,促使我们做出改进,以防止未来的故障。
资源耗尽是一种破坏性特别大的失败模式,因为它允许请求子集使用的服务的失败导致所有请求的失败。例如,假设一个服务调用了一个新的实验性服务,该服务只向1%的用户启动。通常情况下,对这个实验服务的请求需要1毫秒,但由于新服务的故障,请求需要1秒。使用此新服务的1%用户的请求可能会消耗太多线程,导致其他99%用户的请求无法运行。
我们已经发现了一些技术,可以避免这种类型的积累,以较低的假阳性率。
在此算法中,如果队列最后没有为空N
毫秒,那么在队列中花费的时间将被限制为米
毫秒。如果服务已经能够在最后一个N
毫秒,那么在队列中花费的时间被限制为N
毫秒。该算法防止了站立队列(因为lastEmptyTime
会不会在遥远的过去,引起一场米
-ms queuing timeout),同时出于可靠性考虑,允许短时间的排队。虽然具有如此短的超时时间的请求似乎违反直觉,但当系统无法跟上传入请求的速度时,此过程允许快速丢弃请求,而不是增加请求。较短的超时确保服务器总是接受比它实际能够处理的稍微多一点的工作,因此它永远不会闲置。
的值是该算法的一个吸引人的特性米
而且N
往往不需要调整。解决排队问题的其他方法,如设置队列中项目数量的限制或设置队列超时,都需要针对每个服务进行调优。我们找到了一个5毫秒的值米
和100毫秒N
倾向于在广泛的用例集上很好地工作。Facebook的开源Wangle库5提供了这个算法的实现,它被我们的Thrift4框架所使用。
尽管采取了最好的预防措施,还是会发生一些故障。在停机期间,正确的工具可以快速地找到根本原因,将故障持续时间缩短到最小。
高密度的仪表盘与立体主义.在处理事件时,快速获取信息是很重要的。好的仪表板允许工程师快速评估可能异常的度量类型,然后使用该信息假设根本原因。然而,我们发现我们的仪表板变得如此之大,以至于很难快速浏览它们,而且仪表板上显示的图表有太多的行,很难一眼就看清楚。
为了解决这个问题,我们用立体主义构建了顶层仪表盘,2一种用于创建地平线图和折线图的框架,该框架使用颜色对信息进行更密集的编码,便于对多个相似的数据序列进行比较。例如,我们使用立体主义来比较不同数据中心之间的指标。我们围绕立体派的工具允许简单的键盘导航,所以工程师可以快速查看多个指标。图3使用区域图和水平图在不同高度显示同一数据集。在面积图版本中,30像素的版本很难阅读。另一方面,地平线图使得找到峰值非常容易,即使在30像素的高度。
只是改变了什么?由于失败的主要原因之一是人为错误,调试失败最有效的方法之一是查找人类最近发生了什么变化。我们通过一个名为OpsStream的工具收集从配置更改到新软件部署的最新变化信息。然而,我们发现随着时间的推移,这个数据源变得非常嘈杂。由于成千上万的工程师在进行更改,在一次事故中往往有太多的更改需要评估。
为了解决这个问题,我们的工具试图将失败与相关的更改关联起来。例如,当抛出异常时,除了输出堆栈跟踪外,我们还输出由该请求读取的任何配置设置,这些设置的值最近发生了更改。通常,产生许多堆栈跟踪的问题的原因是这些配置值之一。然后我们可以快速地对问题做出响应,例如,通过恢复配置并让做出更改的工程师参与进来。
失败发生后,我们的事件回顾过程帮助我们从这些事件中学习。
事件回顾过程的目的不是推卸责任。没有人因为他或她引起的事件受到审查而被解雇。审查的目的是了解发生了什么,补救导致事件发生的情况,并建立安全机制以减少未来事件的影响。
一种回顾事件的方法.Facebook开发了一种名为DERP(用于检测、升级、补救和预防)的方法,以帮助有效的事件审查。
DERP帮助分析手边事件的每一步。在此分析的帮助下,即使您不能防止这种类型的事件再次发生,您至少可以在下次更快地恢复。
“快速行动”的心态不一定与可靠性相悖。为了使这些理念兼容,Facebook的基础设施提供了安全阀:我们的配置系统可以防止糟糕配置的快速部署;我们的核心服务为客户提供强化的api,以防止出现故障;我们的核心库在面对延迟时防止资源耗尽。为了处理遗漏的不可避免的问题,我们构建了易于使用的仪表板和工具,以帮助找到可能导致正在调查的问题的最近更改。最重要的是,在事故发生后,我们利用吸取的教训使我们的基础设施更加可靠。
相关文章
在queue.acm.org
自动化软件故障报告
布伦丹·墨菲
http://queue.acm.org/detail.cfm?id=1036498
规模失败
乔治Neville-Neil
http://queue.acm.org/detail.cfm?id=2147781
在互联网上提高性能
汤姆•雷顿
http://queue.acm.org/detail.cfm?id=1466449
1.CoDel(可控延时)算法;http://queue.acm.org/detail.cfm?id=2209336.
2.立体主义;https://square.github.io/cubism/.
3.HipHop虚拟机(HHVM);http://bit.ly/1Qw68bz
4.节俭框架;https://github.com/facebook/fbthrift.
5.骗取库;https://github.com/facebook/wangle/blob/master/wangle/concurrent/Codel.cpp.
数字图书馆是由计算机协会出版的。版权所有©2015 ACM, Inc.
没有发现记录