办公区里此起彼伏的短信声、手机铃声,IM 群里铺天盖地的消息,人人都在问:什么情况?服务挂了吗?有没有人在上线?这是在线服务挂了的日常一幕。
没有哪家企业敢承诺自己的服务一定不会宕机,大如谷歌、亚马逊、微软的服务也不时有宕机新闻传出。服务稳定性保障是一个系统而复杂的工程,越来越多技术团队开始投入 SRE、监控、告警、故障定位、应急响应和事故复盘,希望提高稳定性保障工作的确定性。
对稳定性保障团队来说,方案和技术不但要选对,更要避免选错、用错,避免做无用功甚至适得其反。查理芒格说,如果知道我会死在哪里,我将永远不会去那个地方。本文就聊聊线上故障处理和服务稳定性保障中的 6 个常见“死亡之地”,供参考,如有谬误欢迎交流指正。
核心摘要
- 故障处理的第一目标不是立刻找根因,而是快速止损,恢复服务可用性。
- 预案建设不能靠堆数量,要有核心预案和主线思路,否则故障中决策成本会吞掉宝贵时间。
- 告警数量不能代表异常严重程度,团队需要事件中心、告警降噪和北极星指标来聚焦判断。
- 依赖关系、智能化和个人经验都不是不能做,而是不能被当成短期内唯一可靠的故障定位与止损手段。
- 事故复盘的价值不只是解释“为什么挂”,更重要的是沉淀可复制的响应机制、预案和经验。
6 点事故经验总览
| 序号 | 常见误区 | 故障响应中的风险 | 更有效的做法 |
|---|---|---|---|
| 1 | 把日常排障和故障处理混为一谈 | 花大量时间追根因,错过快速止损窗口 | 先做故障特征分析和事件分析,优先恢复服务 |
| 2 | 预案过多 | 真正故障中不知道选哪个,执行链路也可能失败 | 建设核心预案和围绕它的预案集合 |
| 3 | 用报警多少判断异常严重程度 | 重要告警被淹没,隐患被遗漏,过度依赖老司机经验 | 引入事件中心、告警降噪和少量北极星指标 |
| 4 | 执迷于依赖关联关系做定位 | 复杂系统的关联图难维护,短期难以真正指导止损 | 承认边界,把它作为辅助信息而不是唯一抓手 |
| 5 | 把宝都押在智能化上 | 数据质量不稳定时,智能化输出很难可靠 | 先建设标准化、正确、可消费的基础数据 |
| 6 | 过于依赖个人能力 | 老员工离岗后,经验和肌肉记忆无法被快速复制 | 把经验沉淀到流程、配置、产品和预案中 |
错误一:把日常排障和故障处理混为一谈
日常排障和故障处理看起来非常相似,其实是两个有巨大区别的场景。但在谈稳定性保障方案时,很多人会不加区分,认为同一套方案和技术在两个场景里天然通用,更常见的情况是根本没有意识到这是两个场景。
日常排障关注根因,故障处理关注止损
两者最大的区别在于目标不同:
- 日常排障是非紧急场景,核心目标是追查技术根因。
- 故障处理是紧急场景,核心目标是让服务快速止损和恢复。
典型的日常排障包括:追查个别用户请求失败的原因、追查某个模块响应时间变长的原因、追查个别程序实例崩溃的原因。这些异常通常是个例或局部问题,不影响全局。团队可以通过 trace、程序堆栈分析、火焰图、代码分析等手段,最终查出某个程序代码 bug,或某台机器的硬件性能问题。
服务故障则不同。它通常表现为相当比例的用户无法正常使用服务,或者出现大面积服务宕机。这个场景要追求的是尽快止损恢复,需要争分夺秒,越快越好。
事故处理中先看特征和事件
如果一开始就按日常排障思路处理线上故障,动作很可能会慢。故障应急响应首先要做的是故障特征分析和事件分析,再基于特征和事件确定止损方案,例如:
- 流量调度;
- 重启服务;
- 回滚上线;
- 扩容;
- 降级;
- 摘除异常实例。
这些操作不一定需要先知道根因才能执行。只要故障特征或关键事件对症,止损效果会立马显现。
当然,也存在这样的 case:故障中这些手段都用尽了,仍然起不到止损效果。这时不得不深入排查技术根因,但这应该是最后不得已而为之。一旦走到这一步,通常大事故已经酿成。
在稳定性保障中,日常排障和巡检一样,都属于故障预防,可以避免小问题和隐患引发事故;故障处理则处在稳定性保障中最紧迫的位置。如果一开始就按日常排障思路去做故障处理,就好比医生用保健品来挽救将死的病人,药可能有用,但时间等不起。
基于这样的差异,日常排障更多关注个别请求、个别实例这样的点;故障处理则需要更多从全局、从面上分析故障特征和关键事件。这两个场景可以共用很多工具和方法,关键是不能把优先级用反。
更重要的是,当大家都把注意力聚集在排障和根因上时,是不是更应该想想:如何从全局上对故障特征分析和事件分析做一些事情?
错误二:预案过多
想要抢在故障升级前恢复服务,确定故障特征或关键事件后,就需要有预案来应对。但问题也在于,有些服务的预案可能过多了。真到要用时,团队可能不知道该用哪一个,光决策就花去很长时间;终于选中一个,却又执行不成功。
这个问题的关键,可能在于缺乏预案建设的核心思路,只是在漫无目的地打补丁。
好预案要有主线:以多活切流为例
我印象最深刻的预案是一招鲜:多活切流,以及围绕这个核心预案所做的预案集合。
这个预案集合的建设思路是:
- 要让多活切流能发挥作用,就必须控制所有异常的出现都是局部性的,不能所有多活单元里同时出现异常。
- 要做到第 1 点,首先要做好的就是变更和线上操作的灰度控制、灰度策略。机器/容器异常、网络异常这类问题,天然大概率出现在局部,不会多个单元同时出现。
- 要让多活切流能够随时操作,还要保障好单元间的 n+1 资源冗余,以便切流时不至于容量不足。
- 为了平衡 n+1 资源冗余和成本,就要做好服务降级。若切流发生在高峰期,可以先降级后切流。
以上工作做好,基本上 80% 以上的故障都可以在早期得到快速止损,不至于升级为大事故。
核心预案比预案数量更重要
这个预案建设有几个重要特点:
- 核心预案,也就是多活切流,操作简便、生效快。
- 思路和原则清晰,既有利于预案建设和维护,也有利于决策执行,甚至可以做到自动执行。
当然,不同服务的情况要具体分析。比如有的业务没有多活,或者多活建设很困难,不敢随时切流,那就需要另辟思路。核心是要有核心预案和主线思路。那种预案建到哪算哪、像给服务不停打补丁的方案,迟早兜不住。
错误三:用报警的多少来感知服务异常和严重程度
老司机们也许会会心一笑。曾几何时,甚至是现在,有多少团队还是靠报警数量来发现服务故障、判断异常严重程度?
这个做法的问题显而易见:要么容易遗漏重要报警,要么容易遗漏导致事故的隐患。这种模式只有天天浸淫在某个服务中的老司机能够勉强玩转,因为他们可能瞄一眼就知道每个报警的轻重。但一旦换人,立马玩完。
告警要降噪,判断要聚焦
解决这个问题有两种方法:
- 研发或直接引入一个报警降噪的事件中心。
- 从海量指标和报警中抽象出北极星指标,让大家的注意力首先集中在少量关键指标上。
关于北极星指标和 SLO 的具体做法,历史文章中有介绍:《SLO 新解,一种行之有效的故障处理方法》。
两种方法同时使用当然最好。
错误四:执迷于依赖关联关系来做故障定位
依赖关联关系做故障定位,是一个长期以来被持续追求,却又收效甚微的方向。
分析起来可能有两个原因:
- 在现有基础技术上,服务关联关系的获取和更新难度都很高,也缺少打通各个环节的命名规范。
- 这个事情可能陷入了一个悖论:服务复杂才需要这样的关联信息来做问题定位,但复杂服务真画出关联,往往是一团乱麻,而不是一棵清晰的树;如果服务比较简单,其实也用不着把它的关联画出来。
我愿意相信这个方向能有走出悖论、真正开花结果的一天。但如果一个服务着急解决眼前的问题,这个方向可能一时半会还帮不上大忙。
在事故响应中,依赖关系更适合作为辅助判断材料,而不是唯一定位抓手。它能帮助团队理解系统结构,但不能替代故障特征分析、事件分析和可执行的止损预案。
错误五:把宝都押在智能化上
自从 AlphaGo 打败李世石以来,大家就开始期待智能化能够推动运维领域的变革。但目前为止,业界在 AI 智能运维方向上,还鲜有有说服力的案例。针对时序数据趋势的智能预测和异常检测,大概可以算是比较接近智能化的一个实现。
在服务稳定性保障上,大家期望智能化能够解决的最大问题是智能定位问题。虽然和前面的问题一样,要定位个什么结果出来,大家未必想得足够明白,但这个方向已有无数尝试和努力。
智能化的前提是输入数据可靠
要实现智能化,一个很重要的前提是输入数据的正确性和标准化。而目前基础设施参差不齐,运维报警全凭手动配置,80%、90% 的报警可能都是误报。想要在这样的基础上产生智能,大概跟要在垃圾堆里挖出矿来差不多。
我也愿意相信这个方向会迎来真正变革的一天,但短期内不能寄予过高期望,至少不能把解决问题的重心都押在这上面。
错误六:过于依赖个人能力
能够在故障处理中从容应对,在别人还没反应过来的时候就把故障解决掉的老员工,是企业的宝贝。
但问题是,这个宝贝不会一直留在一个岗位上。离职、转岗、升职、休假,都可能让关键经验突然离开一线。
不知道是不是幸存者偏差,据笔者多年的观察,一个核心技术人员的离岗,通常意味着紧接而来的一场大事故。这个准确率简直比天气预报准多了!
原因其实很明显:这个岗位所需的各种信息、各种服务定位止损经验,都存在这个员工的脑子里,甚至是肌肉记忆里,别人无法复制,也无法在短时间内重建这些信息。当老员工离开时,如果这个岗位不能把他的经验留下,那很不幸,这个服务很高概率要靠一场事故来重建保障体系。
事故经验要沉淀成可复制能力
所以,有没有办法把一个老员工的经验留下,融入到这个服务里,或者让新来的人能无缝获取?
这个工作似乎很有挑战,但却很值得尝试。现在有一些产品能够预置故障处理的最佳实践,并将老司机的经验通过配置的方式沉淀到产品中,让经验可复制。也许在智能化真正到来之前,这是更值得探索的方向。
事故复盘应该沉淀什么
服务挂了之后,复盘不能只停留在“根因是什么”。一次有价值的事故复盘,至少应该回到三个问题:
- 这次故障的关键特征和关键事件是什么?
- 哪些止损动作有效,哪些动作太慢、太复杂或无法执行?
- 哪些经验应该沉淀到监控指标、告警降噪、事件中心、预案、配置或产品能力里?
如果复盘只产出一份解释事故的文档,下次还要靠同一批人临场发挥,那学费就没有真正交值。真正有价值的沉淀,是让下一次故障来临时,新人也能沿着清晰的指标、事件和预案快速行动。
FAQ
Q1:故障处理中为什么不能一上来就追根因?
因为线上故障的第一目标是快速止损和恢复服务,而不是立即完成技术根因分析。根因分析很重要,但在相当比例用户无法正常使用服务时,流量调度、回滚、扩容、降级、摘除异常实例等动作往往更紧急。
Q2:日常排障和故障处理可以共用工具吗?
可以。trace、监控、日志、事件、告警等工具都可能同时服务两个场景。关键不是工具能不能共用,而是优先级不能用反:日常排障可以慢慢追根因,故障处理必须先围绕特征、事件和止损动作展开。
Q3:预案是不是越多越好?
不是。预案过多会增加故障中的决策成本,还可能出现选中了预案却执行不成功的情况。更有效的方式是围绕核心预案建设预案集合,让预案有主线、有原则、可维护、可执行。
Q4:告警数量能代表服务故障严重程度吗?
不能。告警数量多,可能只是噪声多;告警数量少,也可能遗漏了关键隐患。更可靠的方式是通过事件中心做告警降噪,并抽象少量北极星指标,让团队先看真正影响服务和用户体验的关键指标。
Q5:智能化能解决故障定位问题吗?
智能化值得期待,但短期内不能把全部希望押在上面。智能化依赖正确、标准化、可消费的输入数据;如果基础设施参差不齐、告警大量误报,智能定位就很难稳定可靠。
Q6:团队如何降低对老员工个人能力的依赖?
要把老员工在故障处理中积累的判断、经验和动作,沉淀到流程、配置、预案和产品能力中。这样新人接手时,不需要从零重建脑子里的经验地图,也能按可复制的方法完成故障响应。
结论
线上故障不可完全避免,真正决定稳定性水平的,是团队如何发现异常、判断影响、快速止损、复盘沉淀。
这 6 点经验背后的核心并不复杂:不要把故障处理当成日常排障,不要用预案数量替代预案质量,不要用告警数量替代判断能力,不要把关联关系、智能化或个人英雄主义当成唯一依赖。服务稳定性保障最终要沉淀为团队能力,而不是某一个人的临场发挥。
关于作者
本文作者华明,Flashcat 合伙人,文章内容是 Flashcat 技术团队共同沉淀的结晶,作者做了编辑整理,我们会持续输出监控、稳定性保障相关的技术文章,文章可转载,转载请注明出处,尊重技术人员的成果。
