服务挂了,学费交了,掌握这6点就值了

华明@快猫星云 2022年11月17日

办公区里此起彼伏的短信声、手机铃声,IM群里铺天盖地的消息,人人都在问,什么情况?服务挂了吗?有没有人在上线?。。这是在线服务挂了的日常一幕。

目前没有哪家企业敢承诺自己的服务肯定不会宕机,大如谷歌、亚马逊、微软的服务也不时有宕机的新闻传出。服务稳定性保障是一个系统而复杂的工程,有越来越多的技术关注在这个领域,以期提高稳定性保障工作的确定性。

对于做稳定性保障的同学来说,在众多稳定性保障方案和技术的选择中,不但要选对,更要避免选错用错,避免做无用功甚至适得其反。查理芒格说,如果知道我会死在哪里,我将永远不会去那个地方。今天就来聊聊那些稳定性保障工作可能的死亡之地,以资参考,如有谬误欢迎交流指正。

错误一:把日常排障和故障处理混为一谈

日常排障和故障处理是两个非常相似其实又有巨大区别的场景。但在谈到方案时很多人往往对它们不加区分,认为自己所用的方案和技术在这两个场景里是通用的(当然更有可能是没有意识到这是两个场景)。

这两个场景有什么区别呢?

最大的区别就在于日常排障是一个非紧急,以追查技术上的根因为主要目标的场景,而故障处理则是一个紧急,以服务的快速止损为主要目标的场景。

典型的日常排障,如追查个别用户请求失败的原因、追查某个模块响应时间变长的原因、追查个别程序实例崩溃的原因等等,这些异常以不影响全局的个例和局部问题为主。可能通过trace、通过程序堆栈分析、通过火焰图、通过代码分析等手段,最后查出是某个程序的代码bug,或某个机器的硬件性能问题。

而服务故障则表现为相当比例的用户无法正常使用服务、大面积的服务宕机。这个场景里要追求的是服务的尽快止损恢复,需要争分夺秒,越快越好。要做到这一点,就不能按日常排障的思路来了。首先要做的是故障的特征分析和事件分析,基于特征和事件来确定一个止损方案,比如流量调度、比如重启服务、比如回滚上线、比如扩容、比如降级、比如摘除异常实例等等。这些操作都不必知道根因就可以执行,而且只要故障特征或关键事件对症,止损效果会立马显现。

当然,也存在这样的case,在故障中这些手段都用尽了仍然起不到止损的效果,这时候就不得不去深入排查技术上的根因,但这应该是最后不得以而为之,而且一旦走到这一步通常大事故已经酿成。

其实在稳定性保障中,日常排障和巡检一样,都属于故障预防,可以避免小问题和隐患引发事故。而故障处理则处在稳定性保障中最紧迫的位置。如果一开始就按日常排障的思路去做故障处理,那就好比医生用保健品来挽救将死的病人,药可能有用,但时间等不起。

基于这样的差异,日常排障更多的是关注在个别请求个别实例这样的点上,而故障处理则需要更多的从全局从面上去分析故障的特征和关键事件。

这两个场景可以共用的工具和方法很多,主要是不能把它们的优先级用反了。

更重要的是,当大家都把注意力聚集在排障和根因上时,是不是更应该想想,如何从全局上对故障的特征分析和事件分析做一些事情?

错误二:预案过多

想要抢在故障升级前恢复服务,确定了故障的特征或关键事件后就需要有预案来应对。但问题也在于有些服务的预案可能过多了,真到要用时可能不知道该用哪一个,光决策就花去很长时间,而终于选中一个却又执行不成功。

这个问题的关键可能在于缺乏预案建设的核心思路,只是漫无目的的打补丁。

我印象最深刻的预案是一招鲜:多活切流,以及围绕这个核心预案所做的预案集合。

这个预案集合的建设思路是:

  1. 要让多活切流能发挥作用,就必须控制所有异常的出现都是局部性的,不能所有多活单元里同时出现异常;
  2. 要做到第1点,首先要做好的就是变更和线上操作的灰度控制和灰度策略。而像机器/容器异常、网络异常,这些天然就是大概率出现在局部,不会多个单元同时出现;
  3. 再有,要让多活切流能够随时操作,还要保障好单元间的n+1资源冗余,以便切流时不至于容量不足;
  4. 为了平衡n+1的资源冗余和成本,就要做好服务降级,以便可以降低冗余,如果切流操作需要发生在高峰期,就可以先降级后切流;

以上工作做好,基本上80%以上的故障都可以在早期得到快速止损,不至于升级为大事故。

这个预案建设有几个重要特点:

  1. 核心预案(多活切流)操作简便、生效快;
  2. 思路和原则清晰,既有利于预案建设和维护,又有利于决策执行,甚至可以做到自动执行;

当然,不同服务的情况要具体分析,比如有的业务多活都没有,或多活建设很困难,不敢随时切流,那就需要另辟思路了。核心是要有核心预案和主线思路,那种预案建到哪算哪,像给服务不停打补丁的方案,迟早兜不住。

错误三:用报警的多少来感知服务异常,以及异常的严重程度

老司机们也许会会心一笑,曾几何时,甚至是现在,有多少团队还是靠这个来发现服务故障的?

这个做法的问题显而易见,要么容易遗漏重要的报警,要么容易遗漏导致事故的隐患。这种模式也只有天天浸淫在某个服务中的老司机能够勉强玩转,因为他们可能瞄一眼就知道每个报警的轻重,但一旦换人立马玩完。

有两种方法解决这个问题,一个是研发或直接引入一个报警降噪的事件中心。另一个是要从海量的指标和报警中抽象出北极星指标,让大家的注意力首先集中在少量的关键指标上,具体做法历史文章中有介绍《SLO新解,一种行之有效的故障处理方法》

两种方法同时使用当然最好。

错误四:执迷于依赖关联关系来做故障定位

这是一个长期以来被持续追求,却又收效甚微的方向。

分析起来可能的原因有二:

  1. 在现有的基础技术上,服务的关联关系获取和更新难度都很高,也缺少打通各个环节的命名规范;
  2. 这个事情可能陷入了一个悖论:服务复杂才需要这样的关联信息来做问题定位,但复杂的服务真画出关联往往是一团乱麻,而不是一颗清晰的树。而如果服务比较简单,那其实也都用不着把它的关联画出来了;

我愿意相信这个方向能有走出悖论真正开花结果的一天,但如果一个服务着急解决眼前的问题,这个方向可能一时半会还帮不上大忙。

错误五:把宝都押在智能化上

自从AlphaGo打败李世石以来,大家就开始期待智能化能够推动运维领域的变革。但目前为止业界在AI智能运维方向上,还鲜有有说服力的案例。针对时序数据趋势的智能预测和异常检测,大概可以算是比较接近智能化的一个实现。

在服务稳定性保障上,大家期望智能化能够解决的最大问题是智能定位问题(虽然和前面的问题一样,要定位个什么结果出来大家未必想得足够明白),这个方向已有无数的尝试和努力。

但要实现智能化,一个很重要的前提是输入数据的正确性和标准化。而目前基础设施参差不齐、运维报警全凭手动配置,80%、90%的报警可能都是误报。想要在这样的基础上产生智能,大概跟要在垃圾堆里挖出矿来差不多。

我也愿意相信这个方向会迎来真正变革的一天,但短期内不能寄予过高的期望,至少不能把解决问题的重心都押在这上面。

错误六:过于依赖个人能力

能够在故障处理中从容应对,在别人还没反应过来的时候就把故障解决了的老员工是企业的宝贝。

但问题是这个宝贝不会一直留住在一个岗位上(离职/转岗/升职/休假。。)。

不知道是不是幸存者偏差,据笔者多年的观察,一个核心技术人员的离岗,通常意味着紧接而来的一场大事故。这个准确率简直比天气预报准多了!

原因其实也很明显,这个岗位所需的各种信息、各种服务定位止损经验都存在这个员工的脑子甚至是肌肉记忆里,别人无法复制或在短时间内重建这些信息。当老员工离开时,如果这个岗位不能把他的经验留下,那很不幸,这个服务很高概率要靠一场事故来重建保障体系。

所以,有没有办法把一个老员工的经验留下,融入到这个服务里,或者让新来的人能无缝获取?

这个工作似乎很有挑战,但却很值得尝试。现在有一些产品能够预置故障处理的最佳实践,并将老司机的经验通过配置的方式沉淀到产品中,让这个经验可复制。也许智能化真正到来之前,这是更值得探索的方向。

关于作者

本文作者华明,Flashcat合伙人,文章内容是Flashcat技术团队共同沉淀的结晶,作者做了编辑整理,我们会持续输出监控、稳定性保障相关的技术文章,文章可转载,转载请注明出处,尊重技术人员的成果。

标签: SRE