首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

大规模系统故障的三大诱因一览

每个故障产生的根本原因各不相同,大规模系统故障并导致故障大范围扩散一般都是三种常见原因。不过对于每一种原因,也有对应方法来防御性措施来减缓故障的大面积扩散。

1. 快速部署的配置变更

配置系统的设计倾向于能够在全局范围内快速复制系统变更。快速的配置变更是一种强大的工具,它可以使工程师快速管理新发布的产品或调整设置。但是,快速的配置变更也意味着,如果部署了错误的配置,将快速引发故障。针对这一问题,为防止因配置变更引发故障,企业可以在实践中采用一系列措施:

让所有人使用同一个公共的配置系统:使用一个公共配置系统可以确保流程和工具在各种类型的配置上均适用。在脸谱,我们发现团队有时会倾向于采用一次性的方式来处理配置问题。避免这种倾向,并采用统一的方式进行系统配置管理是一种事半功倍的提高站点可靠性的方法。

静态验证(statically validate)配置变更:许多配置系统允许采用一些弱类型(loosely typed)的配置方式,如JSON结构。这些配置类型使工程师容易犯一些低级错误,如输错字段名称,在该使用整型的地方使用了字符串类型等。静态验证是捕捉这种低级错误最有效的方法。一些结构化的格式(例如脸谱使用的Thrift)可以提供最基础的配置验证能力。此外,通过编写程序性的验证方法来进行更深入细节的需求验证也不失为一种方法。

运行小规模测试(canary):先将配置部署到小范围的服务中,可以防止出现一些灾难性的变更故障。小规模测试可以采取多种形式。最为常见的是A/B测试,例如只向1%的用户发布新配置。多个A/B测试可以同时运行,从而在一段时间内收集测试数据,跟踪各种性能指标。

然而从可靠性的角度看,A/B测试并不能满足我们所有的需求。面向小部分用户所发布的配置变更,也可能导致相关服务器出现崩溃或内存溢出,很明显这类故障的影响将超出参与测试的有限用户范围。此外A/B测试也非常耗时。在进行微小变更时,工程师们往往不愿意使用A/B测试。因此,脸谱基础设施在小规模的服务器集群中自动测试新的配置。例如,如果我们希望向1%的用户部署一个新的A/B测试,我们会优先选择与访问量较少的服务器相关的1%的用户。我们在短时间内监控这些服务器,确保它们不发生崩溃或其他高可见性的问题。这种机制为所有的配置变更提供了一种基本的“合理性检测”(sanity check),确保不会引发大范围的故障。

保留完好配置:脸谱的配置系统设计成在更新配置过程中发生故障时可以保留原有正确的配置。通常如果不提出特别要求,开发者所创造的配置系统往往会在收到无效配置更新时导致系统崩溃。我们则倾向于构建一种能在这种情形下保留原有配置的系统,并在配置更新失败的情况下向系统操作员发出报警信息。使用旧的配置来运行系统一般要好过向用户返回错误信息。

让回滚变得容易:有时,尽管付出了最大努力,但仍然部署了错误的配置。快速发现错误并回滚到变更之前的配置是解决这种问题的关键。我们的配置系统由版本控制来支持,所以回滚变得容易。

2. 对核心服务的严格依赖

开发者通常假定诸如配置管理、服务发现、存储系统等核心服务永远不会出现故障。然而,这些核心服务中一旦出现哪怕是很短暂的故障,也会造成大规模的事故。

对核心服务数据的缓存:对这类服务的严格依赖通常是没有必要的。这些服务所返回的数据可以以一种方式被缓存下来,使得其中的某一个服务出现短暂的运行中断时,仍可支持大部分服务继续运行。

提供强化的API来使用核心服务:当使用核心服务时,遵循最佳实践而开发的共享库是对这些核心服务的最好补充。例如,一些库可以提供设计良好的应用编程接口,以管理缓存或提供良好的故障处理机制。

执行故障演习:开发者也许会觉得自己开发的应用能够承受核心服务的中断,但在尝试之前,谁也没有把握。对于这些中断,我们必须开发一组系统来进行故障演习,范围从对单机的故障注入,到人工触发的整个数据中心的服务中断。

3. 延迟增加与资源耗尽

某些故障导致服务对客户端的响应时间延迟。这种延迟的增加可能微乎其微(例如人工配置错误造成CPU利用率增加,但仍在服务能接受的范围之内),或者可能趋于无穷大(如线程的服务响应出现死锁)在脸谱,基础设施可以毫无困难地应对少量的访问延迟增加,但大量的访问延迟则会引发连锁故障。几乎所有的服务对等待处理的请求数都有一个上限。这种限制可能是因为在“一个线程处理一个请求”的服务模型中,系统仅能够提供有限的服务线程;或者可能是因为在一个基于事件的服务中,用于处理事件请求的内存是有限的。如果一个服务出现了大量额外的访问延迟,那么调用该服务的其他服务将会面临资源耗尽的问题。这种故障将会在多个服务层级中传播和扩散,从而导致大范围的系统故障。

资源耗尽是一种危害极大的故障模式,因为对一部分请求的处理所引发的故障将会导致所有请求无法被处理。例如,假定一个服务调用了一个新的只发布给1%用户的测试性服务。通常情况下,调用该测试性服务的请求需要花费1毫秒,但由于该服务出现故障,请求的处理时间变为1秒。新服务为了处理这1%用户的请求,要占用更多的处理线程,从而导致其他99%的用户请求无法正常处理。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200727A0VBIB00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券