线上故障应急
这不是“出问题时赶紧修”那么简单
很多团队对故障应急的理解还停留在:
- 报错了
- 找个人看
- 修完发版
这样当然有时也能解决问题。
但它更像临场救火,不是工程体系。
真正成熟的故障应急,关注的是一整条链路:
- 如何尽快发现
- 如何确认影响范围
- 如何建立统一指挥和沟通
- 如何快速止血
- 如何判断是回滚还是热修
- 如何在恢复后留下系统性改进
也就是说,故障应急不是单点技术动作。
它是团队在压力下组织判断和执行的能力。
为什么这件事对前端尤其重要
前端故障常常有一个麻烦的特点:
影响范围看起来很大,但根因分布很散。
同样一个“页面打不开”,背后可能是:
- 静态资源 404
- CDN 缓存异常
- hydration mismatch
- API 失败后没有兜底
- 第三方脚本阻塞
- 特定浏览器兼容问题
- 配置开关错误
所以前端故障既可能是纯前端问题,也可能是边界问题。
这意味着前端团队不能只会看控制台报错。
还要会看:
- 发布链路
- 监控与日志
- 资源分发
- server/client 边界
- 浏览器环境差异
故障响应的第一原则:先恢复,再解释
这是一个很重要的工程原则。
线上故障刚发生时,团队最容易掉进“先把根因彻底查清”的冲动。
但如果核心功能已经明显受损,更优先的问题通常是:
- 能不能快速止血
- 能不能降低影响面
- 能不能把系统拉回一个可接受状态
并不是根因不重要。
而是故障现场的优先级通常应该是:
恢复服务优先,根因分析随后继续。
为什么要做故障分级
不是为了显得规范。
而是因为不同级别的故障需要不同速度、不同人、不同沟通强度。
如果一切故障都当成最高级,团队会疲劳。
如果严重故障没有快速升级,恢复会被拖慢。
一个常见分级方式可以是:
P0
核心链路不可用,或大面积白屏、支付失败、登录瘫痪。
P1
核心功能严重受损,但系统未完全瘫痪。
P2
局部功能异常,对业务有明显影响,但可绕行。
P3
低风险问题,可排入正常修复节奏。
真正重要的不是标签本身。
而是团队是否对“什么算严重”“谁来响应”“多久升级”有共识。
发现故障,靠的不是运气
很多团队对故障的第一发现,仍然来自:
- 用户反馈
- 群里有人说打不开
- 业务同学来问
这说明监控链路还不够成熟。
比较稳妥的发现机制通常包括:
- JS 错误监控
- 资源加载失败监控
- 白屏监控
- 核心接口成功率与耗时监控
- 关键用户路径埋点
- 发布后短时间内的异常波动提醒
没有这些,值班人经常是在“消息传到自己这里”时才算开始响应。
On-call 的本质是什么
不是“轮到谁倒霉”。
而是让系统在任何时间都有明确的第一响应人。
一个健康的 on-call 机制至少要回答:
- 谁是当前第一响应人
- 什么条件下需要升级到更高层
- 发生故障时谁拥有协调权
- 值班材料和 runbook 是否足够
如果这些都没有,轮值制度只会把压力平均分配,却不一定提高恢复效率。
现场处理时,第一个动作通常不是改代码
更实用的第一步一般是建立事实面板。
至少先弄清楚:
- 影响从什么时候开始
- 影响哪些用户和环境
- 最近有什么发布或配置变化
- 现在错误率、白屏率、接口成功率是什么状态
- 是否有快速回滚或关开关路径
如果连这些事实都没站稳,就开始热修,风险会非常高。
一个实用的故障现场流程
1. 确认和定级
值班人先确认故障是否真实存在,并快速评估等级。
2. 建立沟通通道
拉起 war room 或统一群组,避免信息散落。
3. 冻结无关变更
严重故障时,不要让新的发布继续进入现场。
4. 判断是否可快速止血
例如:
- 回滚版本
- 关闭 feature flag
- 切换 CDN 或静态资源版本
- 临时降级某个高风险功能
5. 并行排查
一组人负责恢复,一组人负责定位,一组人负责外部沟通。
6. 恢复后继续根因分析
恢复不是结束。
如果没有根因和后续动作,问题很可能回来。
回滚为什么经常比热修更正确
很多团队在故障现场会本能地想“我马上修个补丁”。
这不总是错。
但如果问题明显来自刚上线的变更,而且回滚路径清楚,回滚往往是风险更低的选择。
因为热修在压力下有几个天然问题:
- 改动没有被充分验证
- 现场信息不完整
- 很容易引入第二波问题
所以成熟团队通常会优先问:
能不能快速回到上一个稳定状态?
如果能,往往应优先这么做。
什么时候更适合 feature flag 止血
如果问题集中在一个新功能、一个实验分支、一个局部模块,而整体版本回滚代价很高,feature flag 是非常有价值的安全阀。
但这有个前提:
开关体系平时就要设计好。
不是出事时才想起来“要不加个开关”。
Source Map 在故障现场的价值
这也是前端故障里非常实用的一环。
线上堆栈往往经过压缩和混淆。
如果 Source Map 管理做得好,团队能更快把错误定位回真实源码。
但也要注意:
- Source Map 的生成策略
- 上传流程
- 访问权限
- 发布版本对应关系
如果版本映射混乱,现场排查会非常痛苦。
这也是为什么 Source Map 不只是“调试工具细节”。
它直接影响故障恢复速度。
前端故障的典型排查路径
面对前端故障时,一个比较稳妥的排查顺序可以是:
1. 看发布
最近是否有版本、配置、资源、开关变化。
2. 看监控波形
错误率、接口耗时、白屏率、加载成功率是否同步波动。
3. 看影响范围
是否只影响某个浏览器、地区、版本、登录态或特定流量。
4. 看边界
问题在前端本身、接口层、缓存层,还是第三方依赖。
5. 看复现条件
是不是冷启动出现,还是某个交互路径后才出现。
这类顺序的价值在于:
先把搜索空间收窄,而不是直接跳进实现细节。
沟通为什么也是应急能力的一部分
故障现场如果没有清晰沟通,团队很容易出现:
- 重复排查
- 信息冲突
- 外部同步延迟
- 责任不清
比较实用的做法通常是明确几个角色:
- incident commander:负责节奏和决策收敛
- responders:负责技术排查和修复
- scribe:负责记录时间线和关键动作
- communication owner:负责对业务或管理层同步
不是每个团队都要正式命名这些角色。
但这些职责最好有人明确承担。
Postmortem 为什么不能只写时间线
故障复盘最容易写成:
- 几点几分发生了什么
- 几点几分恢复
这当然要有。
但这还不够。
真正有价值的 postmortem 至少还要回答:
- 根因是什么
- 为什么现有防线没拦住
- 哪些信号本可以更早发现
- 哪些修复动作能降低复发概率
如果复盘只停留在事件经过,团队学到的东西会很有限。
无责文化为什么不是“没人负责”
这是很多团队会误解的地方。
无责文化的重点不是取消责任。
而是避免把系统性问题简化成“某个人失误”。
成熟复盘会同时承认两件事:
- 人确实可能做了错误操作
- 但真正值得改的是系统为什么允许这种错误造成这么大影响
这才是长期改进的方向。
Runbook 为什么重要
runbook 可以简单理解成故障处理手册。
它的价值不是替代判断。
而是让团队在高压现场不用从零想起。
一个好的 runbook 通常会写清:
- 常见告警代表什么
- 先查哪几个指标
- 常见止血动作
- 回滚路径
- 依赖方联系人
这对新值班同学尤其重要。
前端故障里容易被忽视的几个点
浏览器和设备差异
某些问题在开发机上完全看不到,却会在低端安卓、旧 WebView 或特定浏览器版本里放大。
第三方依赖
分析脚本、登录 SDK、支付脚本、地图服务,都可能成为前端故障入口。
缓存与资源版本错配
HTML、JS、CSS 或配置文件版本不同步时,很容易造成“部分用户出问题、部分用户正常”。
SSR / hydration
现代 React / Next.js 场景里,这是一类非常值得单独警惕的故障源。
中国互联网语境里的现实特点
很多国内业务环境会同时存在:
- 高频发布
- 复杂活动页
- WebView 与小程序并存
- 第三方依赖密集
- 低端设备覆盖广
这会让故障应急更强调:
- 快速止血
- 多环境复现
- 开关和回滚能力
- 白屏、资源和接口的联合监控
海外互联网语境里值得借鉴的点
很多海外工程团队在 incident command、postmortem、runbook、async communication 上积累得更系统。
这和分布式协作、时区协作、SRE 文化有关。
这些做法值得借鉴的不是形式,而是它们共同强调:
故障响应应该被产品化、流程化、文档化。
这类主题为什么很适合做 senior 表达训练
因为它容易被说成一套正确但空的流程:
- 告警
- 排查
- 修复
- 复盘
真正更像 senior 的表达应该能讲出:
- 先恢复还是先查根因
- 回滚和热修怎么判断
- 监控、Source Map、runbook 为什么都在同一条链上
- postmortem 为什么要改系统而不是只追责
建议实践
实践 1:做一次故障演练
练什么:
在可控环境里练发现、定级、沟通和止血。
最小交付物:
一次模拟 incident 的演练记录。
验收标准:
- 有明确 commander
- 有清晰时间线
- 有恢复动作和后续项
常见误区:
- 只练技术修复,不练沟通和角色分工
实践 2:给一个核心链路补 runbook
练什么:
把隐性经验写成可执行手册。
最小交付物:
一份值班处理手册。
验收标准:
- 写清常见告警和排查顺序
- 写清回滚或降级路径
常见误区:
- 写得过于抽象,现场无法直接用
实践 3:写一份真实 postmortem
练什么:
把一次事故转成系统改进材料。
最小交付物:
一份完整复盘文档。
验收标准:
- 有根因
- 有防线缺口分析
- 有可追踪 action item
常见误区:
- 只有时间线,没有系统性改进