尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

事后诸葛亮会议:发布故障复盘与根因分析实战指南

事后诸葛亮会议:发布故障复盘与根因分析实战指南 1. 事后诸葛亮会议从测试到发布的最后一公里先聊一个很多团队都见过的场景。版本上线了功能是新的代码是旧的系统是崩的。测试报告写满了通过发布窗口一切正常结果线上运行三小时之后数据库连接池打满用户反馈蜂拥而至运维一顿操作猛如虎回滚完事。第二天群里安静了问题没人提代码没人改三个月之后同样的问题在另一个模块重新上演。这种循环我见得太多了。无论是做测试的搞运维的还是写代码的都讨厌这种“火灭完就当无事发生”的节奏。问题出在哪不是测试不努力也不是发布流程不规范而是缺少一个关键动作发布之后的事后诸葛亮会议。事后诸葛亮会议业内一般叫Post-mortem Meeting直译过来就是“死后验尸”听着吓人但其实它干的是一件特别朴素的事——把一次发布从测试到上线的全过程重新过一遍找到到底哪个环节出了问题、为什么没拦住、下次怎么改进。它不是追责会不是甩锅会更不是“领导训话会”而是整个研发链路里最能提升团队水平的动作之一。这套东西适合谁来用只要你的团队有测试、有发布、有线上环境无论你是三五人的小创业团队还是几十上百人的成熟研发组都值得建立这种复盘机制。测试工程师能从中知道自己的用例为什么没覆盖到死角开发能搞清楚代码逻辑在真实流量下的表现运维能复盘发布窗口和监控报警是否踩准了节奏管理者则能看清流程里的结构性漏洞。这篇内容我会从复盘会议到底是什么、怎么开才有效、完整的实操流程怎么走、最常见的坑有哪些以及复盘之后怎么把结论真正落地这几个维度把这件事讲透。2. 复盘会到底是什么它不是追责会而是一次系统检查2.1 为什么“测试通过了”还是出了故障很多人对测试有一种误解觉得测试就是“把用例跑一遍全绿就完事”。但真正做过测试的人都知道测试用例是通过“已知问题”反向设计的它的作用是证明“已知场景没有坏”而不是证明“所有场景都正常”。这中间有一道天然的鸿沟。举个例子。你在一个Web API项目里修改了用户登录模块测试用例覆盖了正常密码登录、错误密码提示、验证码过期、账号锁定等场景全部通过。但上线之后用户反复反馈登录卡顿。后来查下来问题出在你改动登录模块时无意中让每次登录请求都触发了一次Redis缓存刷新在高并发下缓存雪崩拖垮了整个会话服务。这就是典型的“测试通过但线上故障”。原因很简单你的测试用例里没有设计“高并发下的缓存行为”这个场景因为你在开发时根本没意识到这个改动会影响缓存。如果你只做了功能测试这个死角永远不会暴露。事后诸葛亮会议的价值正是在这里。发布会暴露出来的问题往往不是“测试不认真”或“开发水平差”这样简单归因能解释的而是一个系统性盲区需求传导时漏掉了一个关键约束设计文档里没写缓存依赖关系测试用例基于错误的理解做了设计发布平台的检查项也没覆盖到相关指标。复盘会要做的就是把这个链条摊开找到盲区在哪一环。2.2 复盘会的三个核心目标一次合格的复盘会至少要达成三个目标。第一个目标是把事实还原清楚。不是“大概是这么回事”而是“在什么时间、由哪次操作、触发了什么行为、产生了什么结果”。这个事实链条要基于监控数据、日志、发布记录、测试报告这些客观证据而不是某个人的记忆。第二个目标是找到根因。这个根因不是表面的“少写了一行代码”或“漏测了一个接口”而是一个可以推导的逻辑链为什么这里会漏是需求评审时信息没对齐还是开发自测时忽略了这个分支或者是测试用例设计时缺少了这个场景问题要一层一层往上追一直追到流程层面或者信息层面。第三个目标是产出可执行的改进项。每个根因都要对应至少一个具体的动作这个动作要有负责人、有完成时间、有验收标准。比如“在下个迭代的测试用例库中增加Redis缓存风暴场景”“在发布检查清单中加入连接池指标项”“在代码评审模板中增加缓存依赖声明要求”。如果没有可执行动作复盘会就是一场集体回忆毫无价值。3. 复盘会怎么开才有效会前准备与会中流程3.1 会前的关键准备先把事实链拼出来我发现很多团队的复盘会开得低效最大的原因不是会议技巧不行而是会前准备严重不足。通常会务组的做法是拉一个会议邀请写上一行“昨日发布故障复盘”然后所有人空着手就来了。开会的时候大家凭记忆讨论A说“我当时测过这个功能”B说“我记得这个接口没改过”C说“好像那个配置是另一个同事改的”一场会开下来全是“我记得”“我感觉”“好像”。正确的做法完全不同。复盘会前必须有一个指定的人通常是牵头这次复盘的技术负责人或资深测试工程师先把事实链整理出来。这个事实链包括几个固定要素时间线。从发布开始每一个关键节点都标出来代码合并时间、构建时间、测试通过时间、发布审批时间、灰度开始时间、全量发布时间、首个异常报警时间、问题确认时间、回滚完成时间。变更清单。这次发布里到底改了什么代码改动涉及哪些模块、配置文件有哪些变化、数据库有没有执行脚本、依赖的第三方服务有没有升级、环境变量有没有调整。异常记录。从监控平台导出异常的完整记录包括异常开始时间、影响范围、错误日志片段、相关指标曲线比如CPU使用率、内存占用、QPS、错误率、慢查询数。测试报告。发布前执行的测试覆盖范围和结果特别要标注哪些用例是跑过的、哪些场景是没覆盖到的。把上面这些信息整理成一张结构化的时间线表在会前发给大家让每个人先自己看一遍。这样开会的时候所有人讨论的就是事实而不是记忆。3.2 会中流程用“五段式”把讨论聚焦复盘会的时间建议控制在45到60分钟。太长容易疲劳太短谈不透。我用的比较多的是“五段式”流程每一步都有明确的时间分配和产出目标。第一段是“陈述事实”大约10分钟。由整理事实链的人把时间线和关键数据过一遍其他人只做补充和确认不讨论原因更不讨论责任。这一步的目的是让大家对“发生了什么”有一个一致的认知。第二段是“问题定位”大约15分钟。大家基于事实链先定位故障的直接触发点。是某一次发布引入了缺陷还是外部依赖发生变化或者是流量增长触发了容量瓶颈。这里要严格基于证据说话避免“我猜”“我觉得”。第三段是“根因分析”大约15分钟。这是整个复盘会最核心的部分。手段是连续追问法从一个直接原因出发一层一层往上问“为什么”。比如直接原因是“Redis缓存雪崩”那为什么缓存会雪崩因为每次登录都触发缓存刷新。为什么每次登录都触发缓存刷新因为代码逻辑里新增了这个调用。为什么这个调用没有被发现因为代码评审时没有人注意到这个新增逻辑与缓存的关系。为什么代码评审没发现因为评审清单里没有“变更是否有外部依赖影响”这个检查项。到这里根因就清晰了不是某个人犯了错而是评审机制里少了一个环节。第四段是“改进措施”大约10分钟。每个根因对应至少一个可执行动作明确到人、明确到时间点。比如“在下周三之前由测试组在自动化测试库中新增缓存压力测试用例验收标准是500并发连续登录30分钟Redis内存和命中率保持在合理区间”。第五段是“会议总结”大约5分钟。主持人把讨论得出的根因和改进项复述一遍确认没有遗漏当场确定各项改进的负责人和截止时间。会议结束后输出一份复盘报告同步给整个研发团队。3.3 时间线工具怎么用这里顺手推荐一个非常实用的做法。事故时间线不要靠手工记录最好使用专门的复盘工具或者用在线协作文档搭建一个模板。我在团队里用的是一个简单模板分为记录时间、操作对象、操作人、操作内容、观测结果、备注六列。从发布开始每次关键操作都追加一行。实际测试下来这个时间线表在复盘会上的价值远超预期因为很多问题是要靠“两个事件之间的时间间隔”来暴露的。比如你有一次发布代码合并时间是上午10点构建完成已经到中午12点半。这中间多了半小时。为什么这么慢查下来是CI服务器上同时有两个项目在构建排队了。那为什么排队没人发现因为构建排队不会失败不报错就不有人关注。这种问题如果只看结果你是永远发现不了的。4. 落地实操一次发布故障复盘会的全过程拆解4.1 案例背景一个“小版本”引发的数据库连接池打满拿一次真实的故障做个演示。某团队上线了一个Web API项目的小版本改动内容只有一个优化用户列表的筛选功能增加了一个“最近活跃时间”的筛选条件。开发自测通过测试用例覆盖了新增筛选条件的正常查询逻辑发布验收也正常。结果上线后10分钟监控平台开始报警数据库连接数飙升。到15分钟的时候数据库连接池被打满大量请求超时整个服务接近不可用。运维在15分钟内执行了回滚服务恢复正常。表面看问题定位很明确新增的筛选条件SQL没有走索引导致慢查询占满了数据库连接。但复盘会要挖的远不止这一层。4.2 复盘时间线还原复盘会前相关负责人把时间线整理了出来09:30开发合并代码到主干分支提交信息为“优化用户列表筛选功能”09:35CI开始构建09:48构建完成自动化测试执行10:05自动化测试全部通过输出测试报告10:20开发提交发布申请发布平台自动部署到预发环境10:35预发环境验证通过仅验证了功能正常11:00发布审核通过开始灰度发布首批10%流量11:05灰度流量引入后数据库连接数开始上升11:08连接数超过阈值触发报警11:12值班人员确认故障开始定位11:18定位到新增SQL的慢查询问题11:20执行回滚操作11:24服务恢复连接数回落这里面有几个关键点值得特别注意。第一灰度发布确实起到了作用在10%流量的时候就触发了报警这是好的设计。第二自动化测试全部通过但没有覆盖SQL查询性能和索引使用情况。第三预发环境验证只做了功能验证没有做数据量模拟预发环境数据库只有几千条数据而线上是几百万条完全不是一个量级。4.3 连续追问根因是怎么一层层挖出来的会议上大家针对“为什么新增SQL没走索引”这个问题开始了连续追问。第一层为什么这个SQL没走索引答开发在编写查询条件时对“最近活跃时间”字段使用了函数包裹比如WHERE DATE(active_time) ?这会导致索引失效数据库不得不做全表扫描。第二层为什么开发会这么写答因为开发没有意识到函数包裹会让索引失效这是一个基础SQL优化知识的盲区。第三层为什么自动化测试没发现性能问题答因为测试用例只验证了查询结果正确性没有做性能断言。测试环境只有几千条数据全表扫描在这个数据量下毫秒级完成根本测不出问题。第四层为什么预发环境也没有发现答因为预发环境的数据库是从生产环境脱敏备份的但只保留了最近一个月的部分数据数据量级不够。第五层为什么发布流程里没有性能测试这个卡点答因为发布流程的设计只覆盖了功能验证没有把性能测试纳入常规发布检查项。追到这里根因已经清晰了。这不是一个“开发写错代码”的单一问题而是一个系统性问题SQL审查规则缺失、自动化测试性能断言缺失、预发环境数据量级失真、发布流程缺少性能检查卡点。四个环节任何一个能拦住这次故障都不会发生。4.4 改进项怎么定根因分析完之后改进项就非常自然地产出了第一项在代码评审模板中增加“SQL查询性能自查”检查项要求开发在提交涉及数据库查询的代码时标注是否使用了索引、是否有全表扫描风险。这项由技术负责人推动下个迭代立即生效。第二项在自动化测试库中增加“慢查询监控”用例要求所有涉及新增查询逻辑的测试必须输出慢查询日志检查结果一旦出现超过阈值的慢查询测试直接判失败。这项由测试组负责两周内完成。第三项预发环境的数据库同步策略调整为全量数据脱敏备份不再截断数据。这项需要DBA和运维协作评估存储和同步成本一个月内完成。第四项在发布流程中增加“性能检查”卡点。对于涉及数据库查询变更的发布必须先在预发环境执行一次基于全量数据的性能压测压测通过才能继续发布。这项由平台组负责两周内上线。这些改进项在会议上达成了共识并明确了责任人和时间点。后续跟踪结果是第二项和第四项按期完成第一项在半个月后也稳定执行了起来第三项因为存储成本问题最终经过评估调整为了“一年活跃用户全量数据同步”虽然没有做到全库同步但已经能覆盖绝大部分核心场景。5. 复盘会上最常见的七种跑偏和踩坑实录5.1 追责式复盘会上沉默会后寻仇复盘会最大的坑就是开着开着变成了追责会。主持人问“这是谁写的代码”大家你看看我我看看你空气突然安静然后开始有人低声解释“当时时间太紧了”“这个需求本来就是临时加的”。这种会开完除了让大家学会“下一次怎么把自己的责任摘干净”什么也得不到。实际上一次可靠的复盘会应该在开场就明确规则不讨论“谁的责任”只讨论“哪个环节出了漏洞”。如果某个人确实有能力问题或态度问题那是绩效管理范畴的事不应该拿到复盘会上来公开批斗。复盘会的对象是系统、流程、机制不是人。我经历过一个团队刚开始做复盘会时所有人都很拘谨。后来技术负责人在开场说了一句话效果立竿见影“今天咱们只聊系统和流程不聊人。包括我自己在内谁的问题都不在会上算账。”从那以后大家才真正开始讲实话。5.2 “我觉得”“应该是”没有证据的猜测式讨论前面说过复盘会最怕没有事实依据的猜测。有人凭印象说“好像是配置问题吧”另一个人接话“我记得之前也出过类似的事”然后话题就越扯越远从配置问题聊到历史纠纷再从历史纠纷聊到团队管理。解决这个问题最直接的办法是主持人控制讨论边界所有观点必须对应到时间线里记录的具体事件和监控数据上。如果没有证据支持就先记下来放到“待确认”清单里等有人拿到实际日志或数据后再来补充。复盘会不是头脑风暴会不发散不跑题。5.3 复盘会开成了“进度汇报会”还有一种跑偏方向是把复盘会开成了各部门的进度汇报。测试说“我们测试用例覆盖了80%”开发说“我们已经把代码修复了”运维说“回滚用了15分钟大家都挺及时”。每个人都在说自己做了什么但没有人真正去分析“为什么这个流程会集体失效”。这种会议表面上和谐实际上完全没价值。复盘的目的是从已知故障中提炼机制改进而不是让各部门来表功或表苦劳。5.4 改进项“研究研究”没有落地的空头支票复盘会上说了一堆“我们要加强测试覆盖”“我们要完善发布流程”“我们要做性能压测”听起来挺有道理但当问起谁来负责、什么时候完成、怎么验收时得到的回答是“后面再研究研究”“回头再说吧”。这种改进项就是空头支票。一次复盘会要产出的改进项必须满足几个硬条件具体的动作、明确的负责人、可接受的完成时间、可以验证的完成标准。做不到这四点就不要写进复盘报告里写了也白写还会消耗大家对复盘机制的信任。5.5 复盘的结论只发表于本次故障有的团队复盘会开得不错根因找得准改进项也定了结果下次发布还是一个样。为什么因为复盘结论只在会上达成了一致没有真正落到团队的工作机制里。比如你定了“自动化测试必须加性能断言”但测试代码的评审机制里没有强制检查这一项下个迭代新写的用例很可能又忘了加。比如你定了“发布流程增加性能检查卡点”但发布平台是外包团队维护的这个需求排了三个月都没排上优先级。要让复盘结论落实需要一种仪式感。我见过一个很有效的做法技术负责人把每次复盘的改进项做成一张“改进项跟踪表”放在团队的项目管理工具里单独建一个列表每周站会时过一遍状态。直到所有改进项关闭之前这个列表一直存在。新来的同事看到这张表也自然知道这是团队对质量的承诺。5.6 把“偶然”当成“原因”有一种很隐蔽的思维误区是把故障归因为“运气不好”“偶发因素”“外部环境特殊”。比如“这次是突然流量暴涨属于偶然事件”“那天数据库刚好在维护正常情况不会出问题”。这种归因方式看起来是在解释问题其实是在逃避问题。复盘时要区分“触发条件”和“根因”。流量暴涨可以是触发条件但为什么系统在流量暴涨时会崩溃这才是根因。流量迟早会涨数据库也早晚要维护如果一个系统的容错能力不够那它迟早会在某个触发条件下出问题只是时间早晚和形式不同而已。5.7 复盘报告写成了“作文”最后一个常见问题是复盘报告本身的格式问题。有人把复盘报告写成了一篇几千字的作文从项目背景开始讲起用了大量形容词核心结论淹没在文字里。这种报告没人愿意看完也没人能从里面快速找到改进项。复盘报告建议控制在两页以内核心内容用表格呈现。直接放时间线表、根因分析、改进项清单。只要这三块内容清晰完整这份报告就是合格的。我自己的习惯是复盘报告在会议结束后24小时内发出时间一长热度减退相关动力和记忆都会打折。6. 复盘之后把结论变成测试与发布流程里的硬卡点6.1 从复盘结论到自动化测试的落地复盘结束只是起点真正的价值在于后续落地。以我前面提到的SQL索引失效为例如果在自动化测试库中增加一条“慢查询监控”用例怎么落地才是有效的首先要确定触发条件。不是所有的查询都需要性能断言只有本次发布涉及的、且设计到新查询逻辑的用例才需要重点关注。可以让测试框架里设置一个开关执行用例时把Slow Query Log打开如果测试过程中出现了超过设定阈值比如500ms的慢查询就自动判定为失败并把SQL语句输出到日志里。其次要设计数据量条件。一个性能测试如果在只有一千条数据的测试库上跑很多性能问题根本暴露不出来。合理的做法是按线上数据量级构造测试数据。可以用数据生成脚本批量插入测试数据或者从预发环境脱敏数据中抽取一部分放入性能测试库。这里我建议测试环境至少模拟线上数据量的十分之一以上才能对索引有效性有一个基本的判断。最后要把这个性能测试串入CI流程里。也就是说构建成功之后、合并到主干之前自动执行一轮包含性能断言的测试。一旦失败自动通知相关开发不让有性能隐患的代码进入主干。6.2 发布流程里的复盘结论固化复盘结论要真正生效最可靠的方式是将其固化成发布流程里的硬性检查项。我见过很多团队的发布流程是“填表”式流程各种检查项都有但实际执行时没人认真核对。这里有一个很实用的技巧把检查项做成“带验证动作”的而不是“带勾选框”的。什么叫带验证动作比如在发布流程中增加“性能检查”卡点不要设置成一个打勾的框而是设置成一个脚本发布平台自动检查预发环境的压测报告是否已生成、压测结果是否满足阈值。如果脚本检查不通过发布按钮直接置灰不给任何手动跳过的口子。如果实在没有条件做到自动化卡点至少也要设置一个“确认人”字段。发布人要发起性能检查确认负责性能测试的同事需要在系统里点击确认留下记录而不是在群里喊一句“测过了没问题”。另外一个值得注意的实践是把复盘中得出的高频故障场景整理成一份“发布风险检查清单”。这份清单放在发布平台的显著位置。发布人提交发布申请时需要逐项勾选是否涉及数据库变更、是否涉及缓存逻辑、是否涉及第三方依赖、是否涉及流量敏感操作。如果涉及高风险项系统会自动提醒需要额外执行对应专项检查。6.3 复盘文化如何持续沉淀复盘会不是一次性的活动而是一种需要持续运营的文化。最有效的运营方式就是让团队里的每个人都“复盘过别人”。我建议轮值机制让不同角色轮流担任复盘会的主持人。测试来主持一次会发现自己在测试用例设计上的盲区开发来主持一次会发现自己在代码评审时忽略的细节运维来主持一次会发现发布平台的能力缺口。这种“换位”带来的认知提升是任何培训都替代不了的。还有一个好用的做法是建立“复盘案例库”。每次复盘的根因分析和改进项整理成一篇脱敏后的案例文档放在团队的Wiki里持续积累。新同事入职后花两天时间把案例库读一遍就能对团队踩过的坑、走过的弯路有一个感性认知。这种方式比任何“新员工培训手册”都管用因为它是从真实事故中沉淀出来的有完整的上下文能让人理解“为什么必须这么做”。7. 我对复盘这件事的一点个人体会做了这么多年的测试和发布相关工作我的体会是真正拉开一个团队交付水平差距的不是某个人的技术水平有多高而是这个团队能不能从自己的错误里持续学习。测试用例写得再多也覆盖不了所有未知场景发布流程设计得再细也拦不住所有可能的疏忽。但只要你有一次高质量的复盘会把每一次失败拆解成可执行的改进项并且真的去落地那这些“事故”就不是纯粹的损失而是团队生长的养分。最后再分享一个自己踩过的坑。有段时间我特别执着于复盘会的“仪式感”每次都要做几十页的PPT把各种数据图表全塞进去结果团队的人都被吓住了觉得复盘是个大事儿参与感反而下降了。后来我砍掉了PPT改成一页时间线、一张根因表、一份改进清单会议时长也压到45分钟。节奏简单了效率反而高了很多。复盘会不是越大越好而是越精确越好。如果你所在团队还没有真正把复盘会跑起来我的建议很直接找最近一次发布出过的问题哪怕它是一个很小的故障按这套方法跑一遍。开完第一次你就会发现它对整个研发流程的推动力远超你的预期。
返回列表