前端知库

线上出了事故怎样处理?事后怎样复盘?

先止血再查根因:确认影响、拉起处理人员、最近有发布就先回滚,同时按固定节奏向相关方同步进展。恢复以后写复盘文档,按时间线还原经过,分析促成因素而不是追究个人,最后落实成有负责人的改进项。回答时用一次真实事故按这个顺序讲。

参考答案

本题是回答思路与示例,不对应某个官方规范。示例中的经历、时间和数字只用来演示怎样表达,讲自己的经历时请用真实数据。

简答

面试官问“遇到过线上事故吗,怎么处理的”,想看的是你在压力下的处理顺序,以及事后能不能让同样的问题不再发生。比如发版后支付页白屏,第一反应不该是打开代码找 bug,而是先让用户恢复使用。

处理时按“止血、定位、沟通”走。先确认影响范围,拉上能处理的人;如果和刚上线的版本有关,最快的办法通常是回滚,或者用功能开关关掉新功能,先恢复服务,根因留到恢复以后再查。处理过程中有一个人负责拍板和分派任务,另有人按固定节奏向业务方、客服同步进展,并记录关键操作的时间。

恢复以后写复盘。复盘文档按时间线还原经过,写清影响有多大、哪些因素促成了事故、哪些地方做得好、哪些地方做得不好,最后列出改进项,每一项要有负责人,能跟踪到完成。

要注意,复盘讲的是“系统哪里让这个错误能够发生”,而不是“谁犯了错”。面试时讲自己的事故,也不要甩锅给同事或者测试,可以坦白自己的失误,重点讲你推动了哪些改进,让同类问题以后能被提前发现。

为什么先止血再查根因

线上事故的每一分钟都在影响用户。查根因可能要几个小时,而回滚一个版本往往几分钟就能完成。所以先做能最快恢复服务的操作,再慢慢查原因。

PagerDuty 公开的事故响应文档就是这样安排的。它给事故指挥者定的目标是尽可能快、尽可能安全地解决事故;在列举修复手段时,第一条就是“部署有问题:回滚”,服务卡死时滚动重启。它也提醒,服务表现异常但负载不高时,要先收集堆转储这类现场数据,再考虑重启,因为重启以后现场就没了。根因分析则放在事故结束之后。

前端常见的止血手段有这几种:

止血时也别忘了留证据。回滚前把错误监控里的报错、出问题的版本号、相关接口的响应截下来,事后定位时才有东西可查。线上报错怎样还原到源码,可以看《线上报错怎样用 Source Map 还原,又不把 map 文件公开?》。

处理过程中谁做什么

事故一乱,最怕的是好几个人同时在线上改东西,或者谁都以为别人在处理。PagerDuty 的做法是分角色:事故指挥者负责决策和分派任务,各领域的专家提出修复建议,但要等指挥者同意才执行;记录员记下重要操作和发现的时间;对外联络人负责更新状态页、发布公告;对内联络人大约每 30 分钟向管理层同步一次进展,文档要求“简短、切中要点”。

小团队不一定分得这么细,但两件事要做到:有一个人拍板,避免各改各的;有人负责同步,让业务方和客服知道影响范围和预计恢复时间,而不是在群里反复追问处理的人。

复盘文档写什么

PagerDuty 要求严重事故都要写复盘,它对复盘的定义是:不追责地详细描述到底是什么出了问题导致了事故,并列出防止类似事故再次发生的步骤,事故响应过程本身也要纳入复盘。它的模板大致包括这几部分:

  • 发生了什么:一两句话的概述。
  • 促成因素:哪些条件共同导致了问题,处理过程中如果有让情况变糟的操作,也写进去,目的是从中学习。
  • 处理办法:怎样恢复的。
  • 影响:要非常具体,写确切的数字,比如持续多久、影响了多少用户。
  • 时间线:问题开始的时间、收到告警的时间、对外公布的时间、关键操作的时间、事故结束的时间,并附上能证明这些时间的日志或监控链接。
  • 做得好的地方和做得不好的地方。
  • 改进项:每一项建成工单,包括防止问题再发生的修复、问题再出现时能更快缓解的准备工作,以及对事故响应流程本身的改进。

PagerDuty 的复盘流程还要求先约好复盘会,再写文档,会议上过一遍时间线,讨论这个问题本可以怎样被发现,比如灰度、测试、压测,再逐条确认改进项。

为什么复盘不追究个人

如果复盘的结果是“找出那个粗心的人批评一顿”,工程师下次出事时就会因为怕被追责而不敢说,事故的确认和解决都会变慢。PagerDuty 的复盘文档引用了对人为失误的两种看法:旧观点认为人犯错导致了故障,新观点把人为失误看成系统问题的表现。无责复盘关注的是错误“是怎样发生的”,而不是“谁犯的”。

落到实际,就是换个问法。不问“你为什么没测”,而问“当时你看到的情况是什么”“这个改动是怎样通过评审和测试进入线上的”。答案往往会指向系统上的缺口:测试没覆盖这种机型,发布流程没有灰度,监控没有对白屏告警。这些缺口才是改进项该补的地方。

一个回答示例

背景:有一次周五下午发版后,大约 15 分钟内错误监控里出现大量 undefined is not a function 报错,集中在低版本安卓的 WebView 上,支付页白屏。

止血:我当时是这次发布的负责人,先在群里说明情况,确认报错只出现在新版本上,就直接回滚到上一个版本,回滚前把报错堆栈和版本号存了下来。回滚后十分钟内报错回到正常水平。期间产品同事负责向客服同步影响范围和处理进度。

定位:回滚后用 Source Map 还原堆栈,发现是新代码用了一个低版本 WebView 不支持的数组方法,而构建配置里的目标浏览器范围在之前一次升级时被改窄了,没有生成兼容代码。

复盘:复盘时我们没有停在“谁改了配置”,而是问为什么这个改动没被发现。最后落实了三件事:目标浏览器配置的改动必须经过评审;发布先灰度 5% 观察 30 分钟;错误监控按版本设置报错突增告警。之后同类问题在灰度阶段就被拦住了。

这个回答的顺序是先恢复、再定位、最后补系统上的缺口,每一步都有具体的动作和时间。面试官往往会顺着追问细节,比如“回滚怎么做到几分钟内完成”“告警阈值怎么定的”,所以只讲你真正经历过、能讲清楚的事故。

常见追问

如果回滚也解决不了怎么办?

说明问题可能不在这次发布,比如是后端接口、第三方服务或者 CDN 出了问题。这时继续按影响面排查:先看监控里报错从什么时候开始、集中在哪些地区和机型,再拉上对应的负责人。同时可以先用降级方案减少影响,比如关掉依赖异常服务的功能、给用户展示明确的提示。

事故是你造成的,复盘时怎么讲?

如实说出自己的失误,但重点放在系统为什么没有拦住它,以及你推动了哪些改进。面试官更看重你能不能从事故里补上流程的缺口,而不是你从来不犯错。

复盘的改进项怎样保证真的落实?

每一项都建成工单,写明负责人和完成时间,在后续的例会上跟进。改进项不要列太多,挑能防止再发生和能更快发现的那几项优先做。