线上 Bug 应急处理——从告警到恢复,一个标准的处理流程
线上 Bug 应急处理——从告警到恢复,一个标准的处理流程
适读人群:有值班经历或者即将开始值班的工程师 | 阅读时长:约16分钟 | 核心价值:一套经过实战检验的线上 Bug 应急处理 SOP,把混乱的危机变成有序的操作
凌晨2点,手机告警响了。
你迷迷糊糊摸到手机,看到的是一条"支付成功率下降至60%,持续3分钟"的告警。
这时候你的脑子是懵的,不知道从哪里开始,不知道先看什么,急得手忙脚乱,乱改一通,结果越搞越乱,本来可能5分钟恢复的问题搞了2个小时。
我经历过这种状态。我也见过另一种状态——有了一套 SOP 之后,同样是凌晨2点收到告警,10分钟内定位问题,20分钟内恢复服务,然后继续睡觉。
两种状态的区别,不在于技术水平有多大差距,而在于有没有一套应急处理的标准流程。
这篇文章我把我的应急处理 SOP 完整写出来。
原则:先恢复,再找原因
这是最重要的原则,很多经验不足的工程师会搞反。
遇到线上故障,很多人的第一反应是:"出了什么 Bug?是哪行代码的问题?"然后开始翻代码、看日志、找根因。
这是错误的优先级。
线上故障的处理有两个阶段:
- 止血阶段:让系统恢复正常,或者至少让损失停止扩大。用时越短越好,目标是分钟级。
- 根因分析阶段:找出到底是什么原因,怎么防止再次发生。可以在系统恢复之后慢慢来,不需要在应急期间完成。
混淆这两个阶段,会导致:一边在挖根因,一边系统还在损失用户,业务损失在扩大。
止血的手段通常是:回滚、降级、限流、切流量,这些操作可以在不知道根因的情况下执行。先执行这些,让系统恢复,再去慢慢查原因。
我的应急处理 SOP
第一步:确认告警是否真实(30秒)
不是所有告警都是真实故障。告警系统本身可能有 bug,监控数据可能有延迟,有时候是误报。
花30秒确认:
- 告警持续时间多长?(刚出现可能是瞬时抖动,持续3分钟以上基本是真实问题)
- 从用户角度看,真的有问题吗?(打开 APP 或者网站,快速验证一下主流程)
- 多个监控维度是否都有异常?(只有一个指标异常,其他正常,可能是监控问题本身)
如果确认是真实故障,进入下一步。
第二步:第一时间通知和拉群(1分钟)
告警确认后,立刻做两件事:
在故障群里发第一条消息:
[故障告警] 支付服务成功率异常
时间:2:03
现象:支付成功率从正常99%下降至60%,持续约3分钟
影响范围:初步判断影响支付主链路,微信/支付宝均受影响
当前操作:正在排查原因
负责人:老张这条消息的目的是让所有关注方知道"有人在处理",避免乱成一锅粥,每个人都在问"是什么问题""有人看了吗"。
通知的对象:值班同事(帮忙搭手)、运维(如果需要权限)、测试(帮忙验证恢复)、业务运营(让他们准备用户沟通口径)。
第三步:快速划定故障范围(3-5分钟)
定范围的核心问题是:这个故障影响了多大的范围?
时间维度:什么时候开始的?开始时间对应什么操作(发版、配置变更、流量突增)?
功能维度:哪些功能受影响,哪些正常?(所有支付都挂了,还是只有某一种支付方式?)
用户维度:是所有用户受影响,还是某个机房/某个地区/某类用户?
依赖维度:是自己的服务有问题,还是依赖的下游服务(数据库、缓存、第三方API)有问题?
这几个维度快速过一遍,通常能把排查范围缩小到2-3个怀疑点。
关键操作:查变更记录
我有一个经验:线上故障有超过70%的概率,是某个最近的变更导致的。先看过去2小时内有没有发版、配置变更、数据库变更、基础设施变更,这个检查往往能让你直接定位到根因。
第四步:执行止血操作
根据第三步的判断,执行对应的止血操作。
如果是最近的发版导致: 立刻回滚到上一个版本。不需要找到具体是哪行代码的问题,先回滚,回滚是最快的止血手段。
如果是下游服务不可用: 判断能不能降级——即在下游服务不可用的情况下,用备用方案(返回兜底数据、走降级逻辑、暂时关闭这个功能)保证主流程可用。
如果是流量突增(比如被刷): 立刻开启限流,保护核心服务,防止雪崩。
如果是数据库问题: 看是连接数满了(加连接、临时扩容)还是某个慢查询拖垮了(kill 掉慢查询,或者临时开启查询缓存)。
止血操作完成后,在群里发更新:
[故障更新] 已回滚至上一版本,支付成功率恢复至98%,恢复时间:2:18
仍在排查根本原因第五步:持续监控,确认恢复稳定(10-15分钟)
止血之后,服务可能恢复了,但不代表问题彻底解决了。要持续观察10-15分钟,确认关键指标恢复正常且稳定,没有出现反复。
同时开始保留现场:把当时的日志、监控截图、错误堆栈都保存下来,供后续根因分析使用。现场很容易消失,特别是有限期的日志和临时监控数据。
第六步:发故障公告(恢复后立刻)
故障恢复后,在故障群和相关业务群发一条故障总结:
[故障恢复] 支付服务异常已恢复
故障时间:2:03 - 2:18,持续约15分钟
影响范围:支付主链路成功率从99%下降至60%
初步原因:疑似最新发版引入,已回滚
恢复方式:回滚至上一版本
影响用户:约XXX笔订单支付失败(已有记录,稍后处理补偿)
后续:明天上午10点进行故障复盘,届时给出根因分析这条公告的目的:让业务团队知道故障结束了,知道影响范围,知道后续有跟进计划。
一次我印象最深的线上故障处理
2021年某天下午,我们的用户服务突然开始大量返回500错误。我当时按照上面的 SOP 处理:
- 确认告警真实——是的,错误持续,不是抖动
- 通知团队拉群
- 查变更记录——发现半小时前做了一次配置变更,把数据库连接池大小从50改成了100
- 查数据库监控——发现连接数确实飙升,但数据库最大连接数是80,100 > 80,连接申请失败
- 立刻回滚配置变更
整个过程10分钟。故障恢复后,我们才去认真分析:为什么有人把连接池配置成了100,是谁做的,当时是什么想法,为什么没有对照数据库实际能支持的连接数来配置。
根因分析在恢复后的第二天才完成,而不是在凌晨故障期间。
提前做好这些,可以让故障处理更顺畅
一、建立完整的监控体系
告警要能做到:从告警到知道"大概哪里有问题",不超过2分钟。这依赖于:分层的监控(用户感知层、应用层、依赖层)和有足够信息量的告警消息(不只是"有问题",还要有基本的上下文)。
二、把常见应急操作变成可以一键执行的脚本
回滚、限流开启、降级开关——这些操作如果每次都要手动找命令、找配置,在紧急情况下会浪费宝贵的分钟,还容易出错。把这些操作脚本化,甚至做成运维控制台的按钮,能显著降低应急处理的难度。
三、演练
每半年做一次故障演练,模拟常见故障场景,让团队成员都练习一遍 SOP。不要等到真实故障发生时才第一次走这个流程。
四、写好 Runbook
Runbook 是应急处理手册,记录常见故障类型的处理步骤。有了 Runbook,即使是新来的同学或者轮班值班的人,也能按图索骥地处理故障。
心态:故障不可避免,慌乱才是最大的敌人
最后说一个心态问题。
线上故障是不可避免的,任何系统都会出故障。区别只在于:你是在慌乱中把事情搞得更糟,还是有条不紊地把损失控制到最小。
我见过因为在紧急情况下手忙脚乱,误操作数据库,把本来可以快速恢复的故障搞成了数据丢失的灾难。
越紧急,越要慢下来,按流程来。SOP 的价值,正是在最混乱的时刻给你一个清晰的行动序列。
故障级别的定义和响应要求
不是所有故障都需要同等级别的响应。提前定义故障级别,能避免小问题过度响应浪费资源,也能确保大问题得到足够的关注。
P0:最高级别,全公司影响 定义:核心业务完全不可用(如支付全挂、用户无法登录),预计影响超过10%的活跃用户。 响应要求:5分钟内必须有人响应,15分钟内要有初步判断,1小时内要么恢复,要么有明确的恢复计划。 通知范围:CTO/技术负责人、业务负责人、客服主管。
P1:高级别,重要功能受损 定义:核心功能降级或部分不可用,但有降级方案,业务影响有限。 响应要求:15分钟内响应,2小时内恢复或有计划。 通知范围:Tech Lead、相关业务方。
P2:中级别,非核心功能异常 定义:边缘功能异常,或只影响少数用户,核心业务不受影响。 响应要求:工作时间内4小时内响应,当天内有方案。 通知范围:值班工程师、团队内部。
P3:低级别,体验问题 定义:页面显示问题、轻微性能下降,不影响核心功能。 响应要求:下个迭代处理。 通知范围:无需立即通知,记录在 Issue 中即可。
故障级别的定义要在平时就确认好,写进团队规范,不能到了出故障的时候再临时讨论"这算 P 几"。
一个值得建立的长期习惯:故障预演
很多故障在发生之前,其实是可以预测到的——如果你做过认真的容量规划和风险分析。
我建议每个季度做一次"故障预演":列出你认为最可能发生的5个故障场景,对每个场景讨论:如果它发生了,我们能多快发现?能多快响应?有没有自动化的手段可以加速恢复?
这个预演过程,往往会暴露出监控盲点、缺失的 Runbook、不清晰的职责分工等问题,提前修复这些,是最低成本的"故障预防"。
