十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从频繁救火到稳定运行:构建系统守护者的完整工作流

从频繁救火到稳定运行:构建系统守护者的完整工作流 凌晨两点十七分手机在枕边震动起来。值班群里已经有一条告警消息订单服务超时率上升。我爬起来打开电脑先看监控面板再看日志确认是数据库连接池被占满。扩容两个只读节点观察十分钟指标恢复正常。群里发了一条“已处理”我躺回床上却没有立刻睡着。因为我知道三周前同样的问题出现过一次。那时我对自己说“下次一定要把连接池参数和应急步骤写下来。”三周后我依然没有写下来。这个场景很多做后端、运维、SRE 的人应该不陌生。我们常常是系统背后的“看护者”——英文里可以叫 The Caretakers。但这里的 The Caretakers 不是某一个团队的名字也不是某款软件的代号。它更像是一种职业状态负责让系统活下去、解释系统为什么异常、处理那些无法写成需求的突发问题。这篇文章想聊的不是某个具体工具而是“The Caretakers”背后的一套工作方法为什么有些人看起来总是很忙系统却反复出问题为什么另一些人做得不多系统却越来越稳。差别不在于加班时长也不在于运气而在于是否完成了从“救火”到“看护”的转变。1. 先搞清楚“The Caretakers”到底在守护什么1.1 守护对象不是单个服务而是服务背后的体验很多人觉得看护者要守护的是进程不挂、接口不报错、磁盘不写满。这些当然重要但它们只是最表层的信号。真正被守护的是用户在一次下单、一次查询、一次上传文件过程中能不能在预期时间内得到结果。所以衡量一个看护者做得好不好不能只看 CPU 使用率和内存水位还要把技术指标翻译成用户体验。比如接口延迟从 80ms 变成 300ms用户可能还感知不到。从 300ms 变成 2 秒页面开始转圈。从 2 秒变成 5 秒用户可能已经退出重进。如果直接超时或返回 500那就是一次明确的事故。这个翻译过程很关键。一个服务是否健康除了看进程是否存活还要看它的延迟、错误率、饱和度趋势。你可能维护的是一个内部中间件没有直接面对终端用户但它支撑的上游服务最终还是要面对用户。所以看护者要建立一条链路基础组件 → 应用服务 → 业务功能 → 用户体验。不同层级之间有关联破案时不能只盯一个点。1.2 守护的边界哪些应该由人处理哪些应该由系统处理一个常见的错觉是告警越多越安全。实际上告警过多等于没有告警。当值班人一天收到几百条通知时他会习惯性忽略真正的大事反而会被淹没。看护者要做的第一件事是定义边界。不是所有异常都需要打断值班人很多异常可以交给系统自动处理或者延迟提醒。边界可以从事故影响来分对用户无感知比如某次重试时间变长但最终成功可以先记一条日志不需要告警。对部分用户有感知但不影响主流程比如某个非核心接口成功率降到 95%可以进入告警队列但不要求立刻响应。影响核心流程用户开始失败比如登录成功率下降、支付超时这类需要 P1 级即时响应。更进一步告警规则应该保留一个有业务含义的描述而不是只给一条“CPU 90%”。因为 CPU 高本身不一定是问题可能是某个批量任务在合理利用资源。你要弄清楚这个指标异常会对哪部分用户、哪个功能、哪个下游造成什么影响。守护的边界既包括技术边界的识别也包括职责边界的划分。看护者不是所有系统的主人但要对“系统是否处于可服务状态”负责。遇到问题时要知道该找谁、该看什么、哪些自己能判断。2. 为什么单点维护解决不了长期稳定问题2.1 救火是条件反射看护是系统思考刚接手一套系统时最常见的心态是先处理眼前的问题。接口报错就重启磁盘满了就清理定时任务没跑就手动补一次。这些动作都有效但它构建的循环是出问题 → 处理 → 不出问题 → 遗忘 → 再出问题。救火式维护的特征是每个动作都只针对当前症状。比如数据库连接池满了你做的动作是重启应用。十分钟后恢复了看起来一切正常。但你可能没有问连接池为什么在那一时刻被占满是慢查询占着连接不放是下游调用方并发突然增加是连接池本身设置过小是代码里存在连接泄漏如果不回答这些问题下一次触发条件出现时同样的故障大概率还会回来。看护者做的是从一次故障中提取出一个模式什么条件下会出现什么问题哪些信号能提前预报哪些参数可以防抖哪些操作可以自动化。救火是条件反射看护是系统思考。条件反射解决的是“让系统先恢复”系统思考解决的是“为什么系统会进到这种状态”。2.2 重复故障是流程失灵的信号系统里最危险的故障不是最难的那个而是重复出现三次以上、却每次都用人工方式临时绕过的那个。重复故障意味着要么原因没有被真正找到要么找到了但没有机制阻止它复发。举一个很常见的例子上线新版本时数据库迁移脚本执行到一半失败。第一个发布人手动回滚第二个发布人又跑了一次同样的操作第三个发布人成功了。三次之后团队开始相信“只要按顺序手动执行就不会有问题”。但问题在于手动步骤依赖人的记忆而记忆不可靠。正确做法是把迁移脚本放进发布流水线增加事务保护并且验证失败后能安全回滚。所以看护者看到一次事故时要判断这是“偶发事件”还是“机制失灵”。机制失灵的典型信号包括同一类告警每周出现。处理步骤每次都不同靠操作者临场发挥。故障发生后没有相关文档更新。新成员不知道如何处理基本告警。如果满足其中两三条就要停下手里的“救火动作”先补机制。哪怕多花一些时间也值得。3. 构建可复用的守护流程从救火到预防要成为一个真正的 The Caretakers不是更努力而是把工作流拆成三段感知、响应、进化。这是一个可以复用到任何系统的框架。3.1 感知让系统状态变得可观测没有观测就没有守护。你无法处理看不到的问题。但观测并不等于把主机上所有指标都采集一遍。一个有效的观测体系应该覆盖四个层次基础设施层CPU、内存、磁盘、网络带宽。这一层解决“机器还能不能撑住”。中间件层数据库连接数、消息队列积压、缓存命中率、连接池等待数。这一层解决“组件是否健康”。应用层接口 QPS、延迟、错误率、调用链状态。这一层解决“程序是否正确工作”。业务层下单成功率、支付成功率、上传完成率、用户登录转化率。这一层解决“业务是否达成目标”。很多团队只做了第一层和第二层第三层和第四层缺失。于是系统 CPU 正常但业务已经不可用了连接池还空着但接口已经长时间卡住。这样的事故不算少见。在设计监控时要遵循“每个指标都有用途”的原则。如果一个指标看不到、无法提供判断依据、也没有关联动作那就先不接入等需要时再加。对于后端服务和中间件可以优先关注四个黄金信号延迟、流量、错误、饱和度。这四个信号基本能描述一个服务的健康状态。延迟请求处理耗时例如 p50、p95、p99。 流量当前请求量例如 QPS、并发数、带宽。 错误请求失败率例如 5xx、4xx、超时次数。 饱和度资源是否快满了例如连接池使用率、磁盘使用率。监控不是越细越好。告警规则要保留足够的上下文并给每个告警打上严重级别。否则值班人会在无效告警中耗光耐心。3.2 响应把应急动作标准化响应是看护者最核心的能力。响应做得好不一定是因为反应快而是因为提前准备好了预案。一个好的预案playbook至少应该包含触发条件什么问题发生时应该使用这个预案。影响评估这个问题会影响哪些服务、哪些用户影响范围多大。操作步骤先做什么再做什么为什么这样做。回滚方案如果操作不成功怎么退回上一步。沟通规则什么时候通知群组什么时候上报。示例数据库连接池使用率超过 90% 时预案可以这样写打开监控面板确认连接池总量和当前活跃连接数。查询慢查询日志定位是否因为某种 SQL 执行过慢导致连接被长时间占用。如果是慢查询导致优先 kill 掉极端慢的会话而不是直接重启应用。如果连接池本身设置过小评估后调整连接池上限并跟踪下游压力。记录复现路径、处理结果和后续优化项。这里的关键是先恢复业务再定位根因。不要在用户已经失败时还在慢慢分析源码。恢复动作可以粗糙但不能扩大风险。扩容、重启、降级、回滚都是常见手段选择哪一个取决于哪个能在最短时间内降低用户影响。同时事故等级要提前定义好。P1 表示核心业务不可用或资损需要立即拉人设一个指挥角色P2 表示某项功能受影响但不致命及时响应即可P3 表示非功能性问题可以记录后跟踪处理。没有分级值班人就会用同一种方式对待所有告警要么过度反应要么延迟处理。3.3 进化从每一起事故中提取改进项故障处理完不等于工作结束。真正让后续日子变轻松的是复盘和进化。复盘不是追责而是把一次故障变成组织能力的增量。一个简单的复盘模板可以包含四列故障现象是什么。根因是什么。直接处理动作是什么。要补的改进项是什么。改进项要分成几类监控类比如增加某个指标告警、补充调用链埋点。代码/配置类比如修复连接泄漏、调整超时时间、修改不合理的重试策略。流程类比如发布前增加数据库迁移检查、变更后自动验证。复盘之后要给每个改进项指定负责人和截止时间然后在下次值班时确认是否落地。没有行动的复盘只是情绪安慰。同样如果发现某些操作重复发生就要考虑自动化。自动化不是一步到位的。你可以从最耗时的几个操作开始比如日志收集、健康检查、发布回滚。把重复性手工操作逐步固化成脚本、流水线、巡检工具这样人才能把精力放在真正需要判断的问题上。4. 高可用不是目的可恢复才是4.1 别把单点当高可用常见误区提到高可用很多人第一反应是“多部署几个实例”。但多实例并不等于高可用。如果两个实例共享同一个数据库而数据库挂了两个实例也一样不可用如果两个实例在同一台机器上机器宕机时也是同时失败如果没有负载均衡和健康检查某个实例已经卡死流量依然会进来。一个真正称得上冗余的部署至少要满足无单点依赖每个组件都有冗余或可替代方案。自动故障转移故障实例能被及时摘除流量切换到健康实例。可验证切换后系统功能正常不是“看起来活着”。数据一致多实例不会导致状态冲突。要在部署图上把每一条链路都画出来标注“如果这条链路断了用户会不会感知”。如果会那这里就是单点。所谓高可用不是堆机器而是把单点一个个去掉并且验证去掉之后系统还能继续工作。4.2 用“故障注入”检验恢复能力高可用设计写进文档里不代表真能用。很多系统在故障发生时才发现“原来健康检查的接口被限流了”“原来切换时连接没有释放”“原来第二机房虽然有数据库但数据延迟了十分钟”。这些问题等到真实事故时才暴露代价最高。所以看护者要做故障演练。不是故意把线上搞挂而是选择安全的时间和范围刻意制造一些小故障验证系统的恢复能力。比如在预发布环境随机杀掉一个业务实例观察流量是否自动转移。给某个服务增加 500ms 延迟观察下游是否超时。把数据库主备切换一次观察应用是否能自动重连。磁盘模拟写满观察告警是否正确触发、日志写入是否受限。故障注入要注意边界。先做最小影响范围选一个非核心服务观察完整链路后再逐步扩展。演练前要有回滚方案演练中要有观察窗口演练后要输出结果。它最重要的目的不是证明系统有多强而是找出恢复路径中那些依赖人的记忆、依赖灵机一动的环节。4.3 数据备份和恢复是最后一道防线很多系统可以接受短暂不可用但不能接受数据丢失。数据备份是看护者最基础也是最容易被忽视的工作。备份不是说“每天导出一份文件”就够了。备份需要回答几个问题备份在哪里不能和源数据放在同一台机器上。备份是否完整全量备份多久一次增量备份多久一次。备份是否可恢复有没有人定期验证过恢复流程保留策略是什么能否恢复到昨天、上周、一个月前的某个时间点实际落地时最容易被低估的是“恢复演练”。团队往往做了备份但从没真正恢复过一次。等到需要恢复时才发现备份文件损坏、版本不兼容、缺少依赖、数据库类型不一致。一个稳妥的检查节奏是每个月做一次小型随机恢复测试验证一个备份文件能否正常拉起服务。每季度做一次完整演练模拟丢失一个核心库把服务恢复到指定时间点。这个过程会暴露大量环境问题、文档缺失、权限盲区。数据恢复是不允许临场发挥的它只能靠提前演练。5. 新手如何从执行者变成真正的看护者5.1 从一次告警开始建立自己的排查闭环如果你刚接触系统不知道怎么开始可以先用一个固定排查链路来处理问题。这个链路不一定万能但能帮你避免瞎猜看现象报错信息是什么是超时、连接失败、没有响应还是结果错误看输入请求参数、文件格式、路径、数据量、上下文是否和预期一致看环境上次变更是什么时候依赖版本、权限、端口、资源配置是否有变化看参数超时时间、重试次数、批量大小、并发数、缓存策略是否合理看日志日志级别够不够关键路径有没有关键日志没有日志时你能不能先补一段日志再复现。看工具边界所用框架、中间件、云服务是否有已知限制是否误用了某个功能每一步都要记录“我看到了什么”“我排除了什么”“我决定做什么”。处理完之后回到原计划把这次排查整理成一篇笔记哪怕只写给自己看长期收益也非常高。5.2 学会写“给未来自己的操作说明”新手往往觉得写文档很浪费时间尤其是给同事看的文档。但真正有价值的文档是写给“三个月后的自己”看的。比如你处理过一个问题消息队列积压导致订单状态不同步。当时你手动重放了消息。不要只写“手动重放消息”而要写出现积压时先看消费者日志是否大量报错。如果消费者报错先锁定报错类型是序列化异常还是下游依赖失败。如果消息体内容不完整不要批量重推先修复数据源。如果只是临时抖动可以按积压量分批重放并观察堆积曲线。这种文档的价值在于别人包括未来的你看到后能够知道“为什么这样做”而不是机械地执行命令。真正可复用的操作说明包含的是判断逻辑。5.3 明确适用边界不是所有系统都需要企业级守护看过那么多监控、告警、剧本、演练也要承认一个现实不是所有项目都适合全套方案。一个人维护一个日活几百的小网站你需要的是基础监控、备份、日志、简单的告警而不是建立一套完整的事故指挥官体系。一个小团队如果只有一两个人值班也不需要把 P1/P2/P3 设计得特别复杂分级要简单可执行。过度工程化同样是一种问题。给一个静态页面服务加熔断、限流、多活架构收益很低。真正应该做的是先保证数据不丢、能访问、能恢复然后根据业务增长逐步增加复杂度。判断投入多少可以问三个问题系统不可用一小时损失有多大数据丢一小时能不能恢复团队每天能拿出多少时间做维护答案会告诉你该用简单脚本还是该上完整平台。The Caretakers 这个角色在工作里往往不显眼。系统稳定时没有人会注意到那些在后台调告警阈值、补日志、更新预案的人系统出问题时他们又总是最快被想起来的人。真正让一个人从“忙乱救火者”变成“从容看护者”的不是知道更多运维命令也不是掌握更多云产品而是建立一套自己的循环看到问题、处理问题、总结模式、改进机制、验证恢复。这套循环一旦转起来系统会越来越稳定你也会越来越清楚每个动作背后的原因。如果你现在还在重复处理某个出现过三次的问题不妨先把处理步骤和判断逻辑写下来再把它交给未来某个也在凌晨醒来的自己。
返回列表