时隔一年,单机房故障自愈又和各位新老朋友见面了,在《单机房故障自愈—黎明之战》中,我们介绍了单机房故障自愈的基础设施建设,包括容灾能力、智能监控平台以及流量调度平台。对于容灾能力的容量建设,需保证服务常态容量满足 N+1 冗余,即在任何一个机房故障情况下,该机房流量能够被其他机房剩余容量所承载。那么当业务流量增长,但资源成本有限,容量无法满足 N+1 冗余时,如何尽可能止损呢?这就是今天要和大家聊的话题,借助服务降级平衡可用性、资源成本和业务效果,实现最大化收益。
重温单机房故障自愈
在大型互联网公司,单机房故障因为其故障时间长,影响范围大,一直是互联网公司及运维人员心头之痛。构成单机房故障的原因,除了常见的物理机房、运营商、链路等基础设施层面故障,也包括突增的用户请求、业务服务的容量不足、程序 Bug、异常的运维变更操作等,都会触发单机房级业务故障的发生。在传统的运维方式中,由于故障感知判断与容量 &流量调度决策的复杂性,通常是人为进行有效止损,但人工介入的时效性会影响服务的恢复速度,而人工决策的不可靠性则可能导致问题的扩大。
为解决这类问题,针对百度内外部网络环境建设了基于智能流量调度的单机房故障自愈能力。结合外网运营商链路监测、内网链路质量监测与业务指标监控构建了全方位故障发现能力,基于百度统一前端(BFE)与内网资源定位服务(BNS)实现了智能流量调度与自动止损能力。同时,基于实时容量预测与实时水位流量来调度自动止损策略与管控风险,从而实现任意单机房故障时业务均可快速自愈的效果。
单机房故障自愈流量调度过程
发生单机房故障时,根据请求流量、服务容量执行流量调度。当服务满足 N+1 冗余时,任何故障机房的流量可全部调度到健康机房,调度完成后没有流量损失。
图 1 满足 N+1 冗余的流量调度
但由于业务使用量的增长,或活动等带来的业务流量突增,机房容量的建设速度并不能完全满足流量的上涨速度。发生单机房故障后,当服务不满足 N+1 冗余时,为了避免过载诱发次生灾害,故障机房的流量不能全部调度到健康机房,调度完成后故障机房仍有部分流量,造成了业务的损失。
图 2 不满足 N+1 冗余的流量调度
如何满足 N+1 冗余
为保证在单机房故障情况下,服务仍然能够满足 N+1 冗余,我们就需要在单机房故障情况下,快速增加健康机房的服务容量,尽量达到 N+1 冗余,减少损失。
扩容是最直观的增加服务容量方式,但在大部分情况下,我们的后备资源有限,缺少足够资源来保证快速扩容。这时我们可以考虑另一种思路,即通过服务降级来裁剪服务部分功能腾出容量空间,实现在服务实例数没有增长的情况下,单个服务实例处理能力的增长,实现容量的增加。
例如推荐类服务,可以将部分个性化内容推荐的步骤裁剪掉,直接返回热门内容,使单次请求带来的系统消耗减少,服务吞吐能力增加。虽然给用户的内容质量有一定损失,但可以保证所有的用户都能正常访问。
图 3 通过服务裁剪进行降级
服务裁剪后健康机房腾出的容量可以承载故障机房的容量,满足了容量的 N+1 冗余。
图 4 通过降级满足 N+1 冗余的流量调度
降级多少合适
降级是通过裁剪服务来实现的,腾出容量的同时对业务效果也有影响,降级对业务的影响可近似用下面的曲线来表示,其中横轴表示降级可腾出的容量,纵轴表示执行该降级后单位流量价值损失,横轴和纵轴所围成的区域表示降级后造成的损失。如某推荐类服务执行降级预案 A 后腾出了 500QPS 的容量,但由于服务裁剪,将造成损失系数为 3 的单位流量价值损失;当执行裁剪更多服务的降级预案 B 后,可进一步将腾出的容量增加到 1500,但损失系数也相应的增加到 6。
图 5 降级造成的单位流量价值损失
从上图可以看出随着降级腾出容量的增加,造成的单位流量价值损失也会增加,所以我们需要权衡降级方案,选择最佳的降级策略,获取最佳收益。
在实际建设中,我们对同一个业务设计多种不同级别的降级方案。降级级别较低的方案,裁剪的步骤少,对业务效果影响较少,但能够腾出的容量也较小,反之降级级别高的方案,裁剪的步骤多,对业务效果影响较大,但能够处理更多的请求。
假设有 N 种可选降级预案,执行第 i 种降级预案归一化到流量的总损失为。总损失有两部分组成,第一部分是故障机房未切走的流量价值损失,由总流量减去健康机房承载的流量计算所得,健康机房承载的流量为降级前健康机房的总容量乘以归一化到流量的容量提升系数。第二部分是降级后健康机房的损失,由健康机房承载的流量乘以归一化到流量后的损失系数计算所得。总损失可表示如下:
故障机房未切走的损失和降级后健康机房的损失之和最小的降级预案就是我们要选取的最佳预案。
如何保证降级操作的安全性
所有的线上操作都存在一定的风险,用于止损的降级预案也不例外,我们历史上也遇到过多次业务线执行预案操作导致整个服务故障的情况,止损操作反而加重了损失。
为保证降级操作的安全性,降级必须分级执行,即严格按照单机房单服务器->单机房全部服务器->剩余机房单服务器 ->剩余机房全部服务器的顺序进行分级操作,各分级之间通过检查指标确认降级操作的安全,当检测到降级异常时能迅速停止正在执行的降级动作。
整个降级预案的分级操作流程如下图所示:
图 6 包含分级的降级过程
降级触发:发生单机房故障时,配置的对应降级动作被自动触发。
执行控制:执行控制部分包含降级过程的主要动作:降级执行、降级检测。
降级执行:完成指定降级动作。为保证安全性,降级预案实现为分级操作,且备份修改前的配置文件以便快速回滚使用。出于时效性考虑,降级动作需要在较短时间内完成,例如10s内完成;
降级检测:每执行一级降级操作后,都要有对应的检测确保此次降级后健康机房不出现异常且降级已生效。
熔断控制:为保证降级的安全性,当某一降级失败时,设置当前降级操作为失败,立刻停止当前正在执行的降级动作并通知人工介入。
如何更快的止损
降级提高了容量空间,那么单机房故障发生时如何对降级操作和流量调度进行合理编排,实现更快速的止损呢?
简单的编排方式是串行执行,即先降级、后切流。降级操作后,调度故障机房流量到健康机房,实现止损。
图 7 降级和流量调度串行执行
但如前文所属,降级操作是一个复杂且耗时的操作流程,既包含降级操作本身的耗时、也包含分级操作带来的等待耗时。一次完整的降级,很可能会持续到分钟级甚至十分钟级别,在降级操作完成前,故障机房带来的损失没有任何缓解。
我们可以以更快的方式来做这件事,即流量调度和降级并行执行。在降级执行完成前,尽量将故障机房的流量调度到健康机房,先保证一部分请求访问正常,在降级结束健康机房容量增加后,继续将故障机房的剩余流量调度到健康机房,实现完整的止损。
并发执行时,降级和流量调度如何进行协同呢?我们设计了容量 DB,该 DB 存储当前服务各机房容量数据,通过容量 DB 协同服务降级和流量调度。降级和流量调度的协同可认为是基于事件的协同,降级操作完成后,将服务降级后的容量更新到容量 DB 中;流量调度服务在并行执行过程中会周期性从容量 DB 中获取最新的容量数据,根据最新的容量和当前的流量进行调度。
图 8 降级和流量调度并发执行
总结
本文介绍了我们在单机房故障自愈中服务降级的实践,上述方案和措施为容量不满足 N+1 冗余的场景提供了故障自愈能力,同时让我们获得了最佳收益,并保证了降级的安全性和时效性。作为《单机房故障自愈》系列的重要一篇内容,服务降级为我们在单机房故障自愈领域的继续探索提供了参考。如果您对故障自愈有好的建议,也请不吝赐教。
作者介绍:
郭晓敏,百度高级研发工程师,负责百度智能运维产品(Noah)故障自愈平台的设计和研发工作,在智能监控、智能故障自愈方向有广泛实践。
本文转载自公众号 AIOps 智能运维(ID:AI_Ops)。
原文链接:
https://mp.weixin.qq.com/s/Up6Q5lX2706onn4nt53t9Q
评论