微型博客的可观测性与 SRE 实践:SLO、告警、容量与故障演练

系统讲解微型博客的可观测性与 SRE 实践:从监控到可观测性的视角转变,四大黄金信号与分层指标体系,SLO 定义、错误预算计算与治理,日志链路的采样与关联,告警分级抑制与降噪,容量规划的压测水位与弹性,混沌工程与故障演练剧本,On-call 值班与事后复盘,以及可观测性数据自身的成本经济学。

线上出问题时,最怕的不是故障本身,而是「不知道哪里坏了」。微型博客的链路短、迭代快、人手少,SRE 实践必须以「用最少的人力守住可用性」为目标:用 SLO 定义什么叫「好」,用错误预算决定「能不能发」,用告警和演练把故障变成可预期的常态。本文讲透这套体系:指标体系、SLO 与错误预算、日志链路、告警降噪、容量规划、混沌演练、值班复盘与成本治理。

前置:系统架构与依赖关系、性能优化与成本治理、限流与过载保护。

目录

1. SRE 视角:从监控到可观测性

监控回答「已知的问题有没有发生」,可观测性回答「未知的问题为什么发生」。

监控(Monitoring):
  预定义指标 + 阈值告警
  回答:系统是否正常?(已知故障模式)

可观测性(Observability):
  任意维度的高基数数据 + 即席查询
  回答:为什么异常?(未知故障模式)
维度监控可观测性
数据聚合指标指标 + 日志 + 链路
问题已知模式未知模式
查询固定看板任意切片
成本低高(需治理)

三支柱的分工:

Metrics(指标):便宜、聚合、适合告警与趋势
Logs(日志):详细、离散、适合定位具体请求
Traces(链路):串联、跨服务、适合定位慢在哪一跳

SRE 的核心心法:用工程手段解决运维问题。可重复的故障响应写成 Runbook,可自动的恢复写成自愈脚本,可预防的故障写成演练剧本——人的精力只留给真正需要判断的部分。

2. 指标体系:四大黄金信号与分层

Google SRE 的四大黄金信号是最小完备的指标集。

信号含义微型博客示例
延迟请求耗时首页 P95、发帖 P99
流量请求量QPS、发帖数/分钟
错误失败率5xx 比例、业务失败率
饱和度资源水位CPU、连接池、队列深度

分层指标体系(避免只看单点):

L1 业务层:发帖成功率、首页可打开率、登录成功率
L2 服务层:各服务 QPS / 错误率 / 延迟(RED 方法)
L3 资源层:CPU / 内存 / 磁盘 / 网络 / 连接池
L4 依赖层:MySQL / Redis / Kafka / 第三方 API
RED 方法(面向服务):
  Rate    请求速率
  Errors  错误数/率
  Duration 延迟分布

USE 方法(面向资源):
  Utilization 使用率
  Saturation  饱和度(排队)
  Errors      错误数

指标的「基数」是最大的工程陷阱:给每个用户 ID 打标签会产生百万级时间序列,直接打爆存储。原则是指标只带低基数维度(服务、接口、状态码、区域),高基数维度交给日志与链路。

3. SLO 与错误预算:定义、计算与治理

SLO 是「用可量化的方式定义什么叫好」,错误预算是「允许坏多少」。

SLI(指标):实际测量值,如「首页请求成功率」
SLO(目标):期望水平,如「30 天成功率 ≥ 99.9%」
SLA(承诺):对外合同,通常比 SLO 宽松
错误预算 = 1 - SLO,如 99.9% → 0.1%(30 天约 43 分钟)

计算方式(滚动窗口):

可用性 SLI = 成功请求数 / 总请求数
延迟 SLI   = P95 延迟 < 300ms 的请求数 / 总请求数

错误预算消耗率 = 已消耗预算 / 总预算
燃尽率(burn rate) = 当前消耗速率 / 均匀消耗速率

多窗口燃尽率告警是最佳实践:

窗口燃尽率阈值含义动作
1h14.4x1 小时烧完 2% 预算页面告警
6h6x6 小时烧完 5% 预算工单
3d1x3 天烧完全月预算复盘

错误预算的治理意义:

预算充足 → 可以激进发布、做实验
预算耗尽 → 冻结发布,全力稳定性
预算持续充裕 → SLO 过松,应收紧目标

SLO 不是越高越好:99.9% → 99.99% 的成本是非线性上升的,要按业务价值定目标。微型博客的首页可以 99.9%,但「删除账号」这类低频关键操作可以要求 99.99%。

4. 日志与链路:采样、结构化与关联

日志与链路的价值在于「出事时能查」,成本在于「量大」。

结构化日志(JSON):
{"ts":"2026-10-02T12:00:00Z","level":"error","svc":"feed",
 "trace_id":"abc123","user_id":"u_1","path":"/api/feed",
 "code":500,"msg":"upstream timeout","latency_ms":1502}

日志的工程要点:

  • 结构化而非字符串拼接:字段可查询、可聚合。
  • 必须带 trace_id:日志与链路靠它串联。
  • 分级与采样:DEBUG 只留本地,INFO 采样,ERROR/WARN 全留。
  • 敏感信息脱敏:手机号、邮箱、token 在写入前脱敏。
采样策略:
- 头部采样:请求入口按比例采样(简单,但可能漏掉慢请求)
- 尾部采样:先收集全部 span,按「慢/错」条件决定是否保留(推荐)
  保留条件:latency > 500ms OR status >= 500 OR 特殊用户

链路的关联能力:

Trace  → Span(每跳耗时)→ Log(该 span 的日志)→ Metric(该跳指标)

三者的粘合剂是 trace_id / span_id,
查询路径:从告警指标 → 找异常 trace → 看该 trace 的日志

高基数排错是链路的最大价值:当问题是「只有某个 Android 版本 + 某个运营商 + 某个区域」时,聚合指标看不出来,只有带这些维度的链路数据能定位。

5. 告警设计:分级、抑制与降噪

告警的目标是「每条都值得半夜起床」,噪声会让人忽略真正的故障。

分级:
P0 页面告警(Page):用户可感知的核心功能不可用 → 立即响应
P1 工单告警(Ticket):影响部分用户或有损 → 工作时间内处理
P2 记录(Log):仅记录,不通知 → 复盘时看
问题现象对策
告警风暴一个故障触发上千条依赖抑制 + 聚合
抖动告警指标毛刺反复触发用 for 持续时长
无行动告警收到也不知道做什么无 Runbook 不上告警
阈值难定静态阈值不适用用 SLO 燃尽率或同比

告警规则示例(Prometheus 风格):

- alert: FeedHighErrorRate
  expr: sum(rate(http_requests_total{svc="feed",code=~"5.."}[5m]))
        / sum(rate(http_requests_total{svc="feed"}[5m])) > 0.05
  for: 5m
  labels: { severity: page }
  annotations:
    summary: "首页错误率 > 5%"
    runbook: "https://wiki/runbook/feed-error"

抑制与聚合是降噪的核心:

抑制(Inhibit):数据库故障时,抑制所有「下游超时」告警
聚合(Group):同一服务的多条告警合并为一条通知
静默(Silence):计划内维护期间静默对应告警

6. 容量规划:压测、水位与弹性

容量规划回答两个问题:能扛多少?什么时候要扩?

容量 = f(峰值 QPS, 单请求资源消耗, 冗余系数)
所需实例数 = 峰值 QPS × 单请求成本 / 单实例容量 × 冗余系数
冗余系数:跨可用区 1.5~2.0,单区 1.3
指标含义水位线
CPU计算水位70% 扩容
内存内存水位75% 扩容
连接池数据库连接80% 告警
队列深度积压程度按消费速率定
磁盘存储水位80% 扩容

压测要点:

1. 全链路压测:从入口打到数据库,避免「网关能扛、DB 先挂」
2. 流量染色:压测流量打标记,与真实数据隔离
3. 阶梯加压:找到拐点(延迟陡增点)而非「最大 QPS」
4. 容量基线:每次大促前重测,代码变更后容量会漂移

弹性伸缩的边界:自动扩容有冷启动延迟(实例启动 + 预热),突发流量靠弹性来不及,必须预留缓冲 + 前置限流。限流是第一道防线,扩容是第二道。

过载保护顺序:
限流(入口)→ 降级(非核心)→ 扩容(加实例)→ 排队(保核心)

7. 故障演练:混沌工程与演练剧本

演练的价值在于「把故障提前到现在」,而不是等它在大促时发生。

混沌实验四要素:
1. 稳态假设:明确「正常」的指标基线
2. 实验变量:注入什么故障(延迟/错误/资源/网络)
3. 爆炸半径:影响范围(单实例/单服务/单可用区)
4. 中止条件:指标恶化到阈值立即回滚
故障类型注入方式验证目标
实例故障杀进程/停容器副本容错、流量摘除
延迟网络延迟注入超时与降级生效
依赖故障屏蔽下游熔断与兜底
资源耗尽打满 CPU/磁盘过载保护
区域故障模拟 AZ 不可用跨区切换

演练剧本示例:

剧本:Redis 主节点故障
1. 稳态:首页 P95 < 200ms,错误率 < 0.1%
2. 注入:kill Redis 主节点
3. 预期:30s 内完成主从切换,期间降级走本地缓存
4. 观察:P95 是否 < 500ms,错误率是否 < 1%
5. 中止:错误率 > 5% 或持续 > 2min → 立即恢复
6. 复盘:切换耗时、降级是否生效、告警是否触发

原则:先在预发演练,再在生产小半径演练;每次演练必须有明确的稳态假设与中止条件,绝不「盲练」。

8. 值班与响应:On-call 与事后复盘

值班体系的目标是「故障发生时有人、有流程、有工具」。

On-call 要素:
- 轮值表:明确 primary / secondary,避免无人响应
- 升级路径:X 分钟未响应 → 升级到 secondary → 再到负责人
- 交接:班次交接必须同步「未决问题 + 进行中的变更」
- 补偿:值班强度可度量,避免倦怠

故障响应流程:

1. 确认(Ack):收到告警立即确认,避免重复通知
2. 止血(Mitigate):先恢复服务(回滚/降级/扩容),再找根因
3. 沟通:建立事故频道,同步状态给相关方
4. 定位(Diagnose):用链路 + 日志 + 变更记录定位
5. 恢复(Resolve):确认指标回到稳态
6. 复盘(Postmortem):无指责复盘,产出行动项

**无指责复盘(Blameless Postmortem)**的核心是「找系统的漏洞,不找人的错」:

复盘项内容
时间线从首次异常到恢复的完整时间线
影响影响用户数、时长、业务损失
根因直接原因 + 系统性原因
检测多久发现?告警是否及时?
响应多久止血?流程是否顺畅?
行动项可验证、有负责人、有截止日期

行动项要防止「写成口号」:每条都应是「可验证的工程改动」,如「给 feed 服务加连接池监控告警」而非「加强监控意识」。

9. 成本与治理:可观测性数据的经济学

可观测性本身也是成本中心,且增长往往失控。

成本构成:
指标:时间序列数 × 保留时长(高基数最贵)
日志:写入量 × 保留时长(量最大)
链路:span 数 × 保留时长(采样率决定)
手段做法节省
指标降基数移除高基数标签50%~90%
日志分级热数据短留、冷数据归档60%~80%
链路采样尾部采样只留慢/错70%~95%
分级存储近期热存、远期对象存储视保留期
按需采集排障时临时开 DEBUG视场景
保留策略示例:
指标  15s 精度留 15 天,1min 精度留 13 个月
日志  热存 7 天(可查),冷存 90 天(归档),之后删除
链路  100% 错误 + 10% 正常,留 30 天

工程要点:SRE 的落地顺序应是「先定义 SLO,再建指标,最后配告警」。没有 SLO,指标就没有目标;没有目标,告警就只能靠拍脑袋定阈值。可用性的提升靠三件事:可观测(知道哪里坏了)、可降级(坏了能退)、可演练(提前坏过)。对微型博客而言,人手有限,最划算的投资是「把重复的响应写成 Runbook、把可自动的恢复写成脚本」,让人只处理真正需要判断的故障。

10. 速查表与一句话记忆

问题一句话答案
监控与可观测区别监控答「是否正常」,可观测答「为什么异常」
核心指标看什么四大黄金信号 + 分层(业务/服务/资源/依赖)
SLO 怎么定SLI 测量 + SLO 目标 + 错误预算 = 1 - SLO
告警怎么定多窗口燃尽率(1h 14.4x / 6h 6x / 3d 1x)
日志怎么留结构化 + trace_id + 分级采样 + 脱敏
链路怎么采尾部采样,错误全留、慢请求全留
告警怎么降噪分级 + 抑制 + 聚合 + 静默 + for 时长
容量怎么算峰值 × 单请求成本 / 单实例容量 × 冗余
演练怎么做稳态假设 + 变量 + 爆炸半径 + 中止条件
成本怎么控指标降基数 + 日志分级 + 链路采样

一句话记忆:SRE 实践 = SLO 定义「好」(SLI 测量 + 错误预算 = 1 - SLO)+ 四大黄金信号与四层指标(延迟/流量/错误/饱和)+ 多窗口燃尽率告警(1h 14.4x 页面 / 6h 6x 工单 / 3d 1x 复盘)+ 结构化日志与尾部采样链路(trace_id 串联)+ 分级抑制聚合静默降噪 + 容量按峰值与冗余计算(限流先于扩容)+ 混沌演练四要素(稳态/变量/半径/中止)+ 无指责复盘与可验证行动项 + 指标降基数与日志分级控成本——用最少人力守住可用性。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「miniblog」更多文章

  1. 国际化与全球化运营架构:文案、时区、多区域部署与合规
  2. API 设计与 GraphQL/BFF 聚合层:Schema 设计、N+1、聚合与缓存
  3. 媒体处理流水线:图片/视频转码、自适应码率与任务编排