04 预案:预案的三板斧指的是什么?
你好,我是白园,今天我们来聊聊可靠性的第四个部分—预案。
在《隋唐演义》中,程咬金以其独特的三招绝技——三板斧,战胜了众多强敌。尽管他掌握的招数不多,但每一招都运用得炉火纯青。预案也是这样,它的价值不在于数量的多寡,而在于其精准性和熟练度。
历史上,超过90%的系统故障都通过一些基础而通用的应急预案得到了有效解决。这些预案的高效和熟练运用是提高故障恢复速度的关键因素。例如,2021年B站遭遇的重大故障,就是通过执行服务回滚和系统重启的策略成功恢复的。
这节课我会给你介绍六个最常用的应急预案,并详细解释它们的执行顺序。我们将探讨如何确保这些预案能够被有效且迅速地执行,以便在面临系统故障时,能够最大限度地减少业务损失。
六大通用预案
六大预案就是 回滚、扩容、重启、切流、限流、降级。这六种预案可以分为三类,第一类是几乎无损的预案,包括切流、扩容;第二类是短时间内有损的预案,包括重启和回滚;第三类是持续有损的预案,包括限流和降级。我们在选择的时候,需要看一下选择哪种或者哪几种,还有操作顺序是怎样的。
切流
切流是一种常见的技术手段,用于在发生单机房故障时保持服务的连续性和可用性。由于流量切换是一种无损操作,它成为处理此类问题的首要选择。在服务部署时,应实施多机房冗余部署策略,至少确保两个机房的冗余,以便在一个机房发生故障时,能够迅速将流量切换到其他正常运行的机房。这里我来介绍几种常见的切流场景。
- 客户端自动故障转移:一种常见的做法是让服务端配置多个域名,端上自动探测这些域名的健康状况。当某个域名的失败率异常升高时,客户端可以自动执行故障转移。这种方法的优势在于能够在故障发生时自动切换服务,无需人工干预,有效应对机房故障和域名封禁等问题。
- DNS层面的流量切换:面对网络故障,如特定地区的网络问题,可以通过修改DNS记录来实现流量的切换。这种方法的优点在于操作简单,只需更改DNS设置即可。然而,DNS更新通常需要至少5分钟才能生效,且完全收敛可能需要更长的时间,这是它主要的局限性。
- 4层(LVS)流量切换:在正常情况下,4层负载均衡设备具备自动故障转移功能,能够在下游服务出现故障时自动切换流量。这种切换的生效时间通常在秒级,响应速度较快。缺点是一旦LVS本身也受到了影响就只能通过客户端或者DNS层面进行切换。
- 7层流量切换(如Nginx):面对内部机房问题,可以在Nginx层面统一切换流量,这种方法的优点是切换迅速,但通常需要人工干预。人工操作缺点就是操作时间会相对比较长。
- 服务层的切换, 比如利用服务网格技术进行服务调用之间的跨机房切换,这种方式的优缺点跟7层切换类似,都需要人工切换。
- 数据库层面的流量切换:如果数据库所在的机房发生故障,我们可以通过数据库层面来控制流量切换,也可以在业务的服务层进行配置,统一执行。推荐的做法是由数据库层面进行流量切换,因为这种方式更灵活、更快,同时呢,也能降低业务操作带来的风险。
注意,虽然流量切换是一种有效的手段,但在执行前必须进行充分的容量评估和准备。在高峰期进行流量切换时,需要确保目标机房有足够的容量来承载转移过来的流量。
扩容相关的预案你可以看一下前面 容量 那一讲里的详细介绍,这里我就不重复了。
重启
重启服务是一种常见的预案手段,但它也具有潜在的风险。因此在执行重启操作时,必须谨慎地分级进行,在紧急情况下也要考虑操作的影响范围。之前我遇到过一个案例,一个关键的核心服务在业务更新后长时间未进行重启。当服务出现故障时,预案中的一个环节是执行降级重启,即修改配置文件并重启服务。当时因为配置跟代码不匹配导致重启失败,最终扩散到了整个服务,核心功能瘫痪了一个多小时。
如果确实需要进行重启,务必要实施分级重启策略,并且在每次重启后仔细观察,确保服务运行正常。只有在确认无误后,才能继续下一步的重启操作。通过这种方式,我们可以最大限度地减少因重启导致的服务中断风险。
降级
降级旨在确保服务在面临资源限制或故障时仍能保持关键功能的运行。所以降级的主要目的其实有两个:资源重新分配和故障屏蔽隔离。
资源重新分配:当系统容量不足时,通过降级非核心服务来释放资源,优先保障核心功能或服务的运行。例如,在网盘服务中,可以暂停在线转码和个性化推荐等非核心功能;在搜索服务中,可以减少搜索结果的数量和实时性;短视频平台可以降低推荐内容的实时性和页面大小,移除电商、直播等商业化元素;电商平台则可以保留商品图片展示,降低或移除视频内容和个性化推荐。
故障屏蔽隔离:在服务出现问题难以迅速定位或恢复的时候,通过逐步降级非核心服务,来达到快速恢复的目的。例如,在一个大规模故障中,如果不确定是哪个接口导致的问题,可以通过逐步降级各个接口来定位问题源头。逐一移除二级接口,如果问题依旧,继续简化至一级服务,并逐一检查一级服务的每个接口,直至找到故障原因并恢复服务。
下面我们来看下实施降级的具体策略。
- 梳理和分级:首先,我们需要梳理服务和接口,把它们分成三个等级。第一级是最关键的服务和接口;第二级是比较重要的服务和接口;第三级就是那些非核心的可以增加用户体验的接口。
- 设置明确的开关:确保有明确的降级开关,并保持上下游服务的连续性。避免出现下游服务已降级,而上游服务仍在不断重试的情况,这可能导致更严重的后果。必须确保上下游服务同步降级,并能识别降级状态。
- 演练:由于降级是一个有损的操作,必须通过演练来验证预案的可靠性。演练可以从测试环境开始,逐步过渡到线上灰度环境(针对特定用户群体),再到线上部分环境(按比例进行)。在演练过程中,要注意控制影响范围,确保不会对生产环境造成不必要的损害。
限流
限流是确保系统稳定性和性能的关键策略,主要通过 控制并发数和请求量 来实现。并发数是指系统能同时处理的任务数量。请求量是指单位时间内系统接收的请求总数。最常见的两种限流算法令牌桶和漏桶算法。
最后注意的是限流一定要多层进行,7层限流、waf限流、服务层限流、DB限流。同时限流一定要依次往下减少,因为上游是对下游的保护。
回滚
在当前普遍采用Kubernetes进行部署的环境下,回滚操作可以视为一次新的部署过程。通常分为分批和蓝绿两种策略,它们各有优势和局限性。
分批回滚 是一种逐步替换旧实例(老版本)的部署方法,通过逐个替换为新实例(新版本),实现服务的平滑过渡。在这个过程中,新旧实例会短暂共存。这种方法的优势在于操作简单,资源消耗相对较少。然而,它的主要缺点是在更新过程中,新旧实例可能因为同时存在,增加了系统不稳定的风险。
蓝绿回滚 涉及同时运行两个完全独立的环境——蓝色环境(旧版本)和绿色环境(新版本)。当新版本准备就绪后,流量会从蓝色环境切换到绿色环境。如果新版本出现问题,可以迅速将流量切回蓝色环境,实现快速回滚。这种方式的优点是能够快速响应问题并保持服务的稳定性,同时新旧版本之间相互隔离,减少了相互影响的风险。不过,蓝绿部署的缺点在于资源消耗较大,因为它需要同时维护两套独立、完整的环境。
如何保障预案有效执行?
这里我分享一下我的经验。在故障学习方面,我们不仅要回顾以往的故障预案,更要深入研究经典案例,学习他人的问题处理经验。在主动演练方面,应定期进行预案演练,确保每个人都能熟练运用。此外,通过不定期实施故障注入,即目前流行的混沌工程方法,检验团队对突发情况的响应速度和应急能力。
定期演练
通过对关键服务进行定期的故障演练,我们可以在真正的业务故障发生之前识别潜在的弱点和风险点,并制定相应的应对措施。这种做法不仅能增强团队对服务的信心,还能提高处理突发事件的能力。演练的频率最好是每月一次,如果时间间隔太久的话,演练可能就会失去作用。
此外,这里还需要明确一下几个关键点。
- 定义清晰的触发条件:明确在何种场景和标准下可以启动预案。例如,如果直播服务无法建立新的长连接,且单列请求量下降超过90%。
- 量化的决策指标:设定可量化的指标来指导决策。例如,如果下游风控服务不可用导致API整体延迟超过预定阈值,并且故障持续时间超过10分钟。
- 可观测性:确保故障发生和预案执行后,系统是可观测的。这意味着需要有适当的监控和日志记录系统来追踪系统状态。
- 简单明了的执行步骤:预案的执行步骤应该清晰、简洁,并经过实践验证。这有助于在紧急情况下快速且无误地执行预案。
- 可回滚性:在故障得到解决后,应能够对预案执行的结果进行回滚。
小结
最后我想分享一下自己这些年在做预案的过程中的一些心得。
在处理问题的时候,应该优先考虑无损预案,也就是那些不会引入新问题的解决方案。在需要迅速响应的情况下,要选择那些能够快速生效的预案。通常流量切换会比回滚生效更快,切流一般在1分钟内,而回滚可能需要5~10分钟。
在紧急情况下,简单直接的预案往往更可靠,减少了执行过程中出错的可能性。在上线过程中如果出现问题,比如你可以选择回滚或修改代码重新上线两种方案。如果选择了修改代码的方案,但由于时间紧迫导致修改不正确引发更大的问题,所以要优先通过回滚来解决问题。
这里我给你一个预案场景的列表与演练模版,你可以参考。
思考题
如果在上线过程中出现故障,同时也出现了容量过载的情况,你应该如何处理呢?欢迎你把思考后的结果分享到评论区,和我一起交流,如果你觉得这节课的内容对你有帮助的话,也欢迎你分享给其他朋友,邀他一起学习。我们下节课再见!