发布与升级虽然事务复杂,但总体上只与集群中服务之间的调用关系有关,与具体业务特性关联不大。真正难工程化的是监控与报警——它需要因人而异、因地制宜,如同私人医生,而非交通工具。
监控的核心目标只有两个:什么东西出故障了,以及为什么它出故障了。前者是现象(Symptom),后者是原因(Cause),找到的原因可能只是中间原因,而非根因(Root Cause)。
然而,发现故障只是第一步。在规模化系统中,软硬件环境故障是必然事件,而非概率事件。追求 24 小时不间断服务,意味着我们必须为所有可能的故障点建立预案。从"看见故障"到"应对故障",构成了一条完整的链路:
现代可观测性(Observability)体系建立在三大支柱之上:
| 支柱 | 数据特征 | 核心价值 | 典型工具 |
|---|---|---|---|
| Logs | 高基数、高体积、非/半结构化 | 事后诊断、审计追踪 | ELK, Loki |
| Metrics | 低基数、低延迟、数值型时序 | 实时监控、趋势分析、报警 | Prometheus, InfluxDB |
| Traces | 请求级关联、跨服务传播 | 分布式根因定位、性能剖析 | Jaeger, Zipkin |
日志系统是监控与报警的底座。广义的日志不局限于程序日志,还包括各类系统指标的时序采集数据——凡时序相关的、持续产生的数据,都可称之为日志。
结构化后的日志存储系统,本质上是一个时序数据库。采用时序数据库做监控的好处是:不依赖特定脚本来判断系统是否正常,而是依赖标准数据分析模型进行报警,使批量、大规模、低成本的数据收集成为可能。
Google SRE 提出的四个黄金指标(Four Golden Signals)是监控设计的核心框架:
延迟:区分成功请求和失败请求的延迟至关重要。"慢"错误比"快"错误更糟——极少量的慢错误请求就可能导致系统吞吐能力大幅降低。
流量:不同系统的流量指标差异很大——Web 服务器用 HTTP QPS,流媒体用网络 I/O 速率,键值存储用每秒交易量。
错误:不只是显式失败(HTTP 500),还包括隐式失败(HTTP 200 但内容报错)和策略性失败(超时即视为失败)。
饱和度:是最需要预测的指标。很多系统在达到 100% 利用率之前性能就会严重下降。延迟增加是饱和度的前导现象——99% 请求延迟可作为饱和度早期预警。
构建监控系统时,平均值具有欺骗性。如果某服务每秒处理 1000 请求,平均延迟 100ms,但 1% 的请求耗时 5s——在依赖多个服务的场景下,某个后端的 P99 延迟很可能成为前端延迟的中位数。
正确做法:将请求按延迟分组计数,构建直方图,边界定义为指数型增长(如倍数约为 3),这是直观展现请求分布的最佳方式。
一个完善的监控系统,不是"报警很多很完善"的系统,而是信噪比高、有故障就报警、有报警就直指根因的系统。
报警设计决策清单:在添加新报警规则前,必须回答以下问题:
高精度数据采集成本高昂。通过采样 + 汇总可以降低成本:
这种方式可以观测短暂热点,又不需要高额的存储成本。
添加监控项是最难的事情——它看起来像事务工作,实际上非常依赖架构能力。少就是指数级的多! 优秀的监控 SRE 不是不停地添加监控项,而是经常重构监控指标,用最少的监控项全面覆盖系统健康状况。
故障域(Fault Domain)是指一个故障可能影响的范围边界。理解故障域的关键在于:故障的影响范围不是均匀的,而是沿着物理和逻辑的边界传播。
故障域越小,影响面越小,恢复越容易。设计目标是:让故障的影响被最小化地隔离在最小故障域内。
一个完整的 API 请求,从用户发出到服务响应,经历多个故障点。每个 IO 操作都是潜在的故障点:
| 故障点 | 故障特征 | 预案策略 | 关键技术 |
|---|---|---|---|
| 用户端网络 | 个体不可控,区域性可调度 | 多链路域名 + 客户端链路选择 | HTTP DNS, 多域名 |
| DNS | 解析中断影响全部入口 | 多权威DNS + 多递归DNS + HTTP DNS | DNS容灾, HTTP DNS |
| 机房 | 整机房服务中断 | 多机房容灾(推荐3AZ) | 3AZ架构, 跨机房流量调度 |
| 机架 | 整机架机器下线 | 服务+数据分散编排 | 反亲和调度 |
| 交换机 | 大范围机器下线 | 双交换机HSRP热备 | HSRP协议 |
| 负载均衡 | 入口级故障 | VIP技术自动切换 | VIP虚IP |
| 业务服务 | 单实例故障 | 无状态设计 + 负载均衡自动重试 | 服务无状态化 |
| 缓存 | 部分实例故障影响命中率 | 一致性哈希 + 自动重建 | 分片算法, 延迟容忍 |
| 数据库/存储 | 主节点故障 | 主从选举 + 过载保护 | Master选举, 限流降级 |
机房级容灾是最复杂也最关键的预案。2AZ 与 3AZ 架构的选择涉及成本与可靠性的权衡:
3AZ 的三大优势:
数据库压力过大导致雪崩时的恢复策略是一个经典难题:
核心原则:先让数据库能正常服务,再逐步放开流量。不是一刀切恢复,而是渐进式释放。
面对故障,三种恢复手段各有适用场景:
| 手段 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 流量切换 | 无状态服务的故障域切换 | 恢复快,影响小 | 只适用于无状态服务 |
| 过载保护(降级) | 有状态服务的过载 | 防止雪崩 | 牺牲部分用户体验 |
| 扩容 | 资源不足导致的过载 | 根本解决 | 扩容需要时间 |
最小切量原则:流量切换应遵循最小切量原则——能用更细粒度的切量消除故障,就不用粗粒度的。
这是影响故障预案策略的核心架构决策:
业务架构应尽量做到"业务服务无状态,状态集中到中间件"——这是强大的基础架构带来的好处,让业务更轻松。
灰度发布能发现大部分短期故障,但无法发现具有长潜伏期的故障。例如数据库规模达到临界点导致的操作异常——故障爆发时点与风险产生时点间隔太远,不容易定位,且对有状态服务而言可能是不可控制的灾难。消除此类风险,只能依靠严谨的白盒代码审查和全面的测试覆盖率。
从可观测性到故障预案,整条链路中存在若干核心权衡:
关键权衡解读:
线上一个故障同时触发大量报警,接警人看到一堆杂乱报警,无法快速定位根因。解决方案:
传统方式用脚本判断系统是否正常,新方式用数学表达式定义报警规则。优势:
持续添加监控项但不做删减和重构,导致监控系统越来越臃肿、信噪比持续下降。正确做法是像代码重构一样定期重构监控指标。
对于原因不清晰的报警,消除故障的最简方法是基于流量调度——迅速把用户请求从故障域切走,同时保留故障现场。
将服务绑定在物理机上,面临硬件故障时被动响应,需要人工配置变更。这不是自治系统,只是高度自动化的脚本系统。
负载均衡实例故障意味着 1/N 的用户受影响。通过 DNS 解析去除故障 IP 的理论可行,但 DNS 生效周期过长(TTL + 递归服务器忽略 TTL)。VIP 技术的解决方案:所有负载均衡实例 IP 为 VIP,一旦检测到主实例故障,立即将流量切换到备实例——恢复时间从小时级降到秒级。
机房故障导致一批 IP 下线,DNS 解析需要去除这些 IP,但传统 DNS 的生效时间与 TTL 相关(可能 1 小时),且部分递归服务器忽略 TTL。HTTP DNS 基于 HTTP 协议提供 DNS 解析,绕过传统 DNS,结合客户端 DNS 缓存,解决 DNS 生效不及时的问题。
2AZ 中一个 AZ 下线意味着数据库一半节点下线,无法选举出新的 Master。这是 2AZ 架构的根本性缺陷——3AZ 架构通过保证多数节点存活来解决此问题。
交叉引用:根因分析方法论见 第52讲,过载保护与容量规划见 第53讲,工程师思维在监控重构中的应用见 第48讲,服务治理宏观视角见 第47讲。