惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
T
Threat Research - Cisco Blogs
美团技术团队
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MongoDB | Blog
MongoDB | Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
G
Google Developers Blog
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
The Register - Security
The Register - Security
Cyberwarzone
Cyberwarzone
F
Fortinet All Blogs
L
LINUX DO - 热门话题
C
Check Point Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Know Your Adversary
Know Your Adversary
S
Security Affairs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
V2EX - 技术
V2EX - 技术
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Martin Fowler
Martin Fowler
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
I
InfoQ
Cisco Talos Blog
Cisco Talos Blog
博客园 - 司徒正美
aimingoo的专栏
aimingoo的专栏
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
L
Lohrmann on Cybersecurity
T
Threatpost
腾讯CDC
Security Latest
Security Latest
K
Kaspersky official blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
Help Net Security
Help Net Security
Forbes - Security
Forbes - Security

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 【Linux 网络子系统深度拆解】内核网络调优方法论:从基准测试到生产验证 排序基准测试:用数据说话
【系统架构设计】SLO 工程:可靠性的量化管理
Liao Tonglang · 2026-04-13 · via 土法炼钢兴趣小组的算法知识备份

你的系统上线了,可用性”挺高的”。具体多高?“反正没怎么出过事。”上个月有没有故障?“好像有一次,持续了几分钟,影响不大。”影响了多少用户?“不太清楚。”

这段对话在无数团队中反复出现。系统稳定性的管理停留在”感觉”层面——感觉还行,感觉没事,感觉问题不大。当产品经理要求加一个高风险的新功能时,工程师说”可能影响稳定性”,产品经理说”上次你也这么说,结果没事”。争论的双方都没有数据支撑。

Google 的 SRE(Site Reliability Engineering,站点可靠性工程)团队在 2003 年就开始面对这个问题。他们的解决方案不是”让系统更稳定”——因为无限稳定的成本是无限的——而是给稳定性一个精确的数字,然后围绕这个数字构建决策框架

这个框架的核心是三个概念:SLI(Service Level Indicator,服务水平指标)、SLO(Service Level Objective,服务水平目标)和 SLA(Service Level Agreement,服务水平协议)。它们不是运维团队的内部指标,而是连接产品、工程、管理层的共同语言。

本文要回答三个问题:

  1. SLI / SLO / SLA 的精确定义是什么,它们之间的关系是什么?
  2. Error Budget(错误预算)如何把”稳定性 vs. 功能开发”从主观争论变成客量化决策?
  3. 怎么用多窗口燃烧率告警替代简单的阈值告警,减少告警噪声?

上一篇中,我们讨论了容灾架构——如何在灾难发生时保障业务连续性。SLO 工程是容灾的另一面:不是应对极端事件,而是管理日常的可靠性水位。


一、SLI / SLO / SLA:从指标到契约

SLI:服务水平指标

SLI 是对系统行为的一个可量化的度量。它必须是具体的、可测量的、有业务含义的。

好的 SLI 的特征:

  • 用户可感知。内部队列长度不是好的 SLI,但”请求延迟”是,因为用户能直接感受到。
  • 可精确定义。“性能”不是 SLI,“第 99 百分位请求延迟”是。
  • 有明确的计算公式。例如:可用性 SLI = 成功请求数 / 总请求数。

常见的 SLI 类型:

SLI 类型 定义 适用场景
可用性(Availability) 成功请求数 / 总请求数 几乎所有在线服务
延迟(Latency) 请求处理时间的分布(通常取 p50、p99) 面向用户的 API
吞吐量(Throughput) 单位时间处理的请求或事件数 数据管道、批处理系统
正确性(Correctness) 返回正确结果的请求数 / 总请求数 搜索、推荐系统
新鲜度(Freshness) 数据更新到可查询之间的延迟 数据仓库、搜索索引
持久性(Durability) 成功存储的数据比例 存储系统

SLO:服务水平目标

SLO 是在 SLI 上设定的目标值。它表达的是:我们承诺这个 SLI 在某个时间窗口内达到某个水平。

例如:

  • “过去 30 天内,API 可用性 >= 99.9%”。
  • “过去 30 天内,API 第 99 百分位延迟 <= 300 毫秒”。

SLO 的关键特征:

  1. 有时间窗口。99.9% 的可用性是每天?每周?每月?每个选择的含义完全不同。
  2. 低于 100%。SLO 永远不应该是 100%,因为 100% 的可靠性是不可能的,追求 100% 意味着不允许任何变更,这会杀死产品迭代。
  3. 是内部目标,不是外部承诺。SLO 是工程团队给自己设定的标准。

SLA:服务水平协议

SLA 是与外部客户签订的法律契约。如果服务未达到 SLA 约定的水平,服务提供方需要承担后果(通常是经济赔偿)。

SLA 通常比 SLO 宽松。例如:

  • SLO:99.95% 可用性。
  • SLA:99.9% 可用性(未达标则赔偿月费的 10%)。

SLO 和 SLA 之间的差距是一个”安全边际”。如果 SLO 和 SLA 设为相同值,那么一旦 SLO 被突破,就立刻触发赔偿——没有任何缓冲。

三者的关系

graph LR
    SLI["SLI<br/>指标:我们度量什么"] --> SLO["SLO<br/>目标:我们期望达到什么水平"]
    SLO --> SLA["SLA<br/>契约:未达标的后果是什么"]
    SLI --> |"成功请求/总请求"| M1["99.95%"]
    M1 --> SLO
    SLO --> |"安全边际"| SLA
    SLA --> |"赔偿条款"| C["客户补偿"]

二、选择好的 SLI

选择 SLI 是 SLO 工程中最关键的一步。选错了 SLI,后面的所有工作都是在错误的方向上努力。

基于请求的 SLI vs. 基于窗口的 SLI

基于请求的 SLI(Request-based SLI):每个请求独立判断是”好”还是”坏”,然后计算好请求的比例。

可用性 SLI = 状态码非 5xx 的请求数 / 总请求数

适用于请求-响应模式的在线服务(HTTP API、gRPC 服务等)。

基于窗口的 SLI(Window-based SLI):把时间切分为固定长度的窗口(例如每分钟),每个窗口判断是”好”还是”坏”,然后计算好窗口的比例。

可用性 SLI = 数据同步延迟 < 5 秒的分钟数 / 总分钟数

适用于后台服务、数据管道等非请求-响应模式的系统。

SLI 的度量点

同一个 SLI,在不同位置度量,结果可能截然不同。

用户浏览器 → CDN → 负载均衡 → API 网关 → 应用服务 → 数据库
   ①          ②       ③         ④          ⑤         ⑥

在位置 ⑤ 度量的延迟可能是 20 毫秒,但用户在位置 ① 感受到的延迟可能是 200 毫秒(加上 DNS 解析、TCP 握手、TLS 协商、网络传输、前端渲染等)。

原则:SLI 应该尽可能靠近用户度量。 如果用户通过 HTTP API 访问服务,那么在负载均衡器或 API 网关处采集的请求日志是最佳的度量点——它既靠近用户端,又在你的控制范围内。

避免虚荣指标

以下指标看起来有用,但作为 SLI 容易误导:

  • CPU 使用率。CPU 使用率 80% 不意味着用户体验差,CPU 使用率 20% 也不意味着用户体验好。它是容量指标,不是用户体验指标。
  • 错误日志数量。错误日志可能包含大量无害的 warning,也可能遗漏了没被记录的真正错误。
  • 平均延迟。平均值会掩盖长尾延迟。p50 = 10ms、p99 = 5000ms 的系统,平均延迟可能只有 50ms,但 1% 的用户等了 5 秒钟。

太紧的 SLO

如果 SLO 设为 99.999%(“五个九”),意味着每月只允许 26 秒的不可用时间。这意味着:

  • 任何常规发布都可能消耗掉全部预算。
  • 团队不敢做任何变更,产品迭代停滞。
  • 告警噪声极大,工程师疲于奔命。

太松的 SLO

如果 SLO 设为 99%,意味着每月允许 7.2 小时的不可用时间。这意味着:

  • 系统可以每个月宕机半天,用户已经忍无可忍了。
  • Error Budget 永远用不完,SLO 形同虚设。
  • 团队对可靠性没有任何约束力。

合理的 SLO 怎么定

  1. 从历史数据出发。过去 90 天,系统的实际可用性是多少?如果实际可用性是 99.95%,SLO 可以设为 99.9%——比实际稍低,留出合理的操作空间。
  2. 考虑用户期望。用户对延迟 200 毫秒和延迟 500 毫秒的感知差异很大,但对延迟 50 毫秒和延迟 100 毫秒的感知差异很小。SLO 应该反映用户真正关心的阈值。
  3. 考虑依赖方的 SLO。如果你的系统依赖一个 SLO 为 99.9% 的外部服务,你的系统的 SLO 不可能高于 99.9%(除非你有降级方案)。
  4. 逐步收紧。先从一个保守的 SLO 开始,积累数据后再逐步收紧。从 99.9% 收紧到 99.95% 远比从 99.99% 放松到 99.95% 容易被团队接受。

不同可用性等级的停机时间参考

SLO 可用性 年度允许停机时间 月度允许停机时间 每日允许停机时间
99%(两个九) 3.65 天 7.2 小时 14.4 分钟
99.9%(三个九) 8.76 小时 43.8 分钟 1.44 分钟
99.95% 4.38 小时 21.9 分钟 43.2 秒
99.99%(四个九) 52.56 分钟 4.38 分钟 8.64 秒
99.999%(五个九) 5.26 分钟 26.3 秒 0.86 秒

四、Error Budget:把稳定性变成可消费的资源

Error Budget(错误预算)是 Google SRE 最重要的概念之一。它的核心思想是:如果 SLO 不是 100%,那么 SLO 与 100% 之间的差距就是你”允许犯错”的空间

计算方法

如果 SLO 是 99.9% 的可用性,每月的 Error Budget 是:

Error Budget = 1 - SLO = 1 - 99.9% = 0.1%
每月总请求数 = 1000 万
允许的失败请求数 = 1000 万 × 0.1% = 1 万

或者按时间计算:

每月总分钟数 = 30 × 24 × 60 = 43200 分钟
允许的不可用分钟数 = 43200 × 0.1% = 43.2 分钟

Error Budget 的消耗

Error Budget 像一个存款账户。每次故障都会从中”消费”一部分:

  • 一次持续 10 分钟的服务中断,消耗了 10 / 43.2 = 23.1% 的月度 Error Budget。
  • 一次影响 0.5% 请求的 Bug,在持续 2 小时期间消耗的 Error Budget = 0.5% × 2 小时 / 720 小时 = 0.0014%,占月度总预算的 1.4%。

Error Budget 策略

当 Error Budget 还有剩余时——团队可以:

  • 正常发布新功能。
  • 做架构实验(例如测试新的数据库引擎)。
  • 进行混沌工程演练。

当 Error Budget 即将耗尽或已经耗尽时——团队必须:

  • 冻结非关键功能的发布。
  • 优先修复可靠性问题。
  • 增加发布过程中的审核步骤(例如从自动部署退回到手动审批部署)。
  • 开展事后复盘(Postmortem),找出根因并制定预防措施。

这就是 Error Budget 的仲裁价值。产品经理说”我要上新功能”,工程师说”系统不稳定不能上”——这个争论没有赢家,因为双方都在用主观判断。但如果引入 Error Budget:

  • Budget 充足 → “数据显示我们有足够的 budget,可以上。”
  • Budget 不足 → “数据显示 budget 已经不够了,必须先修稳定性。”

争论的对象从”人的判断”变成了”数据”,这是 SLO 工程最大的组织价值。

flowchart TD
    A["每月 Error Budget 重置"] --> B{"当前 Budget 剩余"}
    B -->|充足 > 50%| C["正常迭代<br/>功能发布、实验"]
    B -->|告警 20%-50%| D["谨慎迭代<br/>增加发布审批<br/>优先修复已知问题"]
    B -->|耗尽 < 20%| E["冻结功能发布<br/>全力修复可靠性<br/>事后复盘"]
    C --> F["监控 Budget 消耗速率"]
    D --> F
    E --> G["恢复 Budget 后解冻"]
    G --> F
    F --> B

五、多窗口燃烧率告警

传统的可用性告警方式是设定一个固定阈值:如果过去 5 分钟的错误率超过 1%,就触发告警。这种方式有两个严重问题:

  1. 告警太多(高噪声)。短暂的错误率波动(比如一次网络抖动导致 5 秒内错误率飙升到 5%,然后立刻恢复)会频繁触发告警,工程师被告警疲劳淹没。
  2. 告警太慢(低灵敏度)。低速率的持续故障(比如错误率持续在 0.5%,远低于 1% 的阈值)可能不会触发告警,但如果持续一整天,消耗的 Error Budget = 0.5% × 24 小时 / 720 小时 ≈ 1.67%,30 天下来就消耗了 50%。

Google SRE Workbook 提出的解决方案是多窗口燃烧率告警(Multi-Window, Multi-Burn-Rate Alerting)

燃烧率(Burn Rate)

燃烧率是 Error Budget 消耗速率的倍数。

燃烧率 = 实际错误率 / (1 - SLO)

如果 SLO = 99.9%(允许错误率 = 0.1%):

  • 当前错误率 = 0.1% → 燃烧率 = 1x(正好按预算速度消耗)。
  • 当前错误率 = 0.5% → 燃烧率 = 5x(以 5 倍速度消耗 budget,30 天的 budget 只够用 6 天)。
  • 当前错误率 = 1.4% → 燃烧率 = 14x(30 天的 budget 只够用 2.14 天)。

多窗口策略

单一时间窗口的燃烧率告警仍然有问题:短窗口(5 分钟)容易误报,长窗口(1 小时)反应慢。解决方案是同时检查两个窗口:

  • 长窗口:确认问题确实在持续,不是瞬时抖动。
  • 短窗口:确认问题是当前正在发生的,不是窗口期内已经恢复的历史问题。

Google SRE Workbook 推荐的配置:

告警级别 长窗口 短窗口 燃烧率阈值 Budget 消耗占比(如果持续) 响应要求
紧急(Page) 1 小时 5 分钟 14.4x 2%(1 小时内) 立即响应
紧急(Page) 6 小时 30 分钟 6x 5%(6 小时内) 立即响应
工单(Ticket) 3 天 6 小时 1x 10%(3 天内) 工作时间处理

Prometheus 实现

以下是基于 Prometheus 的多窗口燃烧率告警规则示例:

# 预聚合:计算不同时间窗口的错误率
groups:
  - name: slo-error-rate
    rules:
      # 5 分钟窗口错误率
      - record: slo:http_request_error_rate:5m
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
          /
          sum(rate(http_requests_total[5m]))

      # 30 分钟窗口错误率
      - record: slo:http_request_error_rate:30m
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[30m]))
          /
          sum(rate(http_requests_total[30m]))

      # 1 小时窗口错误率
      - record: slo:http_request_error_rate:1h
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[1h]))
          /
          sum(rate(http_requests_total[1h]))

      # 6 小时窗口错误率
      - record: slo:http_request_error_rate:6h
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[6h]))
          /
          sum(rate(http_requests_total[6h]))

  - name: slo-burn-rate-alerts
    rules:
      # 紧急告警:14.4x 燃烧率,1h/5m 双窗口
      - alert: SLOBurnRateCritical
        expr: |
          slo:http_request_error_rate:1h > (14.4 * 0.001)
          and
          slo:http_request_error_rate:5m > (14.4 * 0.001)
        labels:
          severity: critical
        annotations:
          summary: "SLO burn rate critical: 14.4x"
          description: "Error budget will be exhausted in less than 2 hours."

      # 紧急告警:6x 燃烧率,6h/30m 双窗口
      - alert: SLOBurnRateHigh
        expr: |
          slo:http_request_error_rate:6h > (6 * 0.001)
          and
          slo:http_request_error_rate:30m > (6 * 0.001)
        labels:
          severity: warning
        annotations:
          summary: "SLO burn rate high: 6x"
          description: "Error budget will be exhausted in less than 5 days."

Grafana Dashboard 设计

SLO Dashboard 需要回答三个核心问题:

  1. 当前状态:现在 SLO 达标吗?用一个大号的指示灯(绿/黄/红)。
  2. Budget 剩余:这个周期还剩多少 Error Budget?用一个进度条。
  3. 消耗趋势:按当前速度,Budget 会在什么时候耗尽?用一条趋势线。
┌─────────────────────────────────────────────────┐
│  API 可用性 SLO: 99.9%                            │
│  ┌───────┐  ┌──────────────────────┐             │
│  │ 🟢    │  │ Budget: 72% 剩余     │             │
│  │ 达标   │  │ ████████████░░░░░    │             │
│  └───────┘  └──────────────────────┘             │
│                                                   │
│  当前可用性: 99.94%  |  月初至今 Error Budget 消耗: 28%│
│  ────────────────────────────────────────────     │
│  Budget 消耗趋势                                   │
│  100%|                                   ╱        │
│      |                               ╱            │
│      |                           ╱                │
│      |     当前消耗线 ────────╱                     │
│      |─────────────────                           │
│    0%|________________________________ 时间        │
│       1日      10日      20日     30日              │
└─────────────────────────────────────────────────┘

六、SLO 作为架构决策的仲裁者

SLO 不仅仅是告警的依据。在架构决策中,SLO 提供了一个客观的判断框架。

场景一:要不要引入缓存层

“缓存能提升性能”是一个模糊的理由。用 SLO 来分析:

  • 当前 p99 延迟 SLI = 800 毫秒,SLO 目标 = 500 毫秒。
  • 引入缓存后,缓存命中时 p99 延迟 = 50 毫秒,缓存未命中时 p99 延迟 = 850 毫秒(多了一次缓存查询的开销)。
  • 预计缓存命中率 = 85%。
  • 预计 p99 延迟 = 0.85 × 50 + 0.15 × 850 = 170 毫秒。满足 500 毫秒的 SLO。

但缓存引入了新的故障模式:缓存集群不可用时,所有请求穿透到数据库,可能导致数据库过载。需要评估这个故障模式对可用性 SLO 的影响。

场景二:要不要做服务拆分

一个单体服务的可用性是 99.95%。如果拆分成 3 个串行调用的微服务,假设每个微服务的可用性也是 99.95%:

串联系统可用性 = 99.95% × 99.95% × 99.95% = 99.85%

可用性从 99.95% 下降到 99.85%,月度停机时间从 21.9 分钟增加到 65.7 分钟。如果 SLO 是 99.9%,这个拆分方案直接导致 SLO 无法达标。

这不意味着不能拆分,但意味着拆分后必须通过其他手段(重试、熔断、降级)来补偿可用性损失。SLO 让这个权衡变得可量化。

场景三:数据库选型

在选择数据库时,不同产品的可靠性特征不同:

  • 选项 A:云厂商托管数据库,SLA 99.95%,延迟 p99 = 5 毫秒。
  • 选项 B:自建数据库集群,预估可用性 99.9%,延迟 p99 = 2 毫秒。

如果服务的 SLO 是 99.95% 可用性,选项 B 的 99.9% 可用性已经低于服务 SLO,仅数据库一个组件就可能耗尽全部 Error Budget。选项 A 虽然延迟稍高,但可用性更有保障。


七、SLO 驱动的组织行为

SLO 的影响不仅限于技术层面,它改变了组织的行为模式。

产品 vs. 工程的冲突仲裁

最常见的冲突是:产品团队想快速发布新功能,工程团队想花时间修复技术债务和提升稳定性。

没有 SLO 时,这个冲突的解决方式通常是:谁的职级高听谁的,或者谁声音大听谁的。结果是要么稳定性被牺牲(系统频繁出故障),要么迭代速度被牺牲(团队变得过度保守)。

有 SLO 和 Error Budget 后,规则变成:

  • Error Budget 充足 → 产品优先。工程团队不能以”稳定性风险”为由阻止功能发布——数据证明我们有足够的犯错空间。
  • Error Budget 不足 → 稳定性优先。产品团队不能要求”赶紧上线”——数据证明我们已经没有犯错空间了。

这个机制的关键是双方在事前就同意了规则。Error Budget 策略应该以书面文件的形式存在,由产品负责人和工程负责人共同签字。

发布节奏的量化管理

SLO 和 Error Budget 还可以用来量化发布的”安全余量”。

假设每次发布平均消耗 2% 的月度 Error Budget(来自灰度发布期间的少量错误)。如果月度 Error Budget 总量是 43.2 分钟,那么每次发布平均消耗 0.864 分钟。一个月最多可以做 43.2 / 0.864 ≈ 50 次发布。

如果团队想增加发布频率(比如从每周发布改为每日发布),就需要降低每次发布消耗的 Error Budget——这意味着需要投资更好的灰度发布机制、更完善的自动化回滚、更细粒度的特性开关(Feature Flag)。

事后复盘的量化标准

什么事故值得做事后复盘(Postmortem)?一个实用的标准是:消耗了超过 N% 月度 Error Budget 的事故

例如:

  • 消耗 > 20% Budget → P1 事故,必须做 Postmortem,48 小时内完成。
  • 消耗 5-20% Budget → P2 事故,建议做 Postmortem,一周内完成。
  • 消耗 < 5% Budget → P3 事故,记录即可,不强制 Postmortem。

这比传统的”影响了 X 个用户”或”持续了 X 分钟”的分类标准更有意义,因为 Error Budget 已经综合考虑了影响范围和持续时间。


八、工程案例:某电商平台的 SLO 落地实践

以下案例来自国内某中型电商平台的公开技术分享,展示了从”没有 SLO”到”SLO 驱动”的转变过程。

背景

  • 团队规模:约 80 名工程师,15 个微服务。
  • 业务规模:日活用户约 200 万,日均订单约 30 万笔。
  • 痛点:每次大促后都有大量故障复盘,但复盘结论难以落地;产品和工程团队之间关于”先上功能还是先修 Bug”的争论持续不断。

第一步:选择 SLI(第 1-2 周)

团队识别出 3 个核心用户旅程(User Journey):

  1. 商品浏览:用户搜索商品 → 查看商品详情。
  2. 下单支付:加入购物车 → 提交订单 → 完成支付。
  3. 物流查询:查看订单状态 → 查看物流信息。

为每个旅程选择了 SLI:

用户旅程 SLI:可用性 SLI:延迟
商品浏览 搜索 API 成功率 搜索 API p99 延迟
下单支付 下单 API 成功率 下单 API p99 延迟
物流查询 物流 API 成功率 物流 API p99 延迟

度量点选择在 API 网关层(Nginx 访问日志),因为这是距离用户最近的可控度量点。

第二步:设定 SLO(第 3-4 周)

基于过去 90 天的历史数据:

SLI 历史实际水平 设定的 SLO
搜索 API 成功率 99.95% 99.9%
搜索 API p99 延迟 420 毫秒 500 毫秒
下单 API 成功率 99.92% 99.9%
下单 API p99 延迟 850 毫秒 1000 毫秒
物流 API 成功率 99.97% 99.9%
物流 API p99 延迟 200 毫秒 300 毫秒

SLO 设定略低于历史水平,给发布和实验留出 Error Budget。

第三步:建设可观测性(第 5-8 周)

  • 部署 Prometheus 采集 Nginx 日志中的请求状态和延迟。
  • 使用 Prometheus Recording Rules 预计算各 SLI 的窗口聚合值。
  • 搭建 Grafana SLO Dashboard,包含 SLI 实时值、Error Budget 剩余百分比、燃烧率趋势。
  • 配置多窗口燃烧率告警,接入 PagerDuty 和企业微信。

第四步:制定 Error Budget 策略(第 9-10 周)

产品总监和技术总监共同签署了 Error Budget 策略文件:

  1. 每月 1 日重置 Error Budget。
  2. Budget > 50%:正常迭代,每周发布。
  3. Budget 20%-50%:增加发布前的 Staging 环境验证步骤,取消”紧急发布”通道。
  4. Budget < 20%:冻结功能发布,全力修复可靠性问题,直到 Budget 恢复到 30% 以上。
  5. 大促期间(双十一前后两周):冻结所有非关键变更。

效果

运行 6 个月后的数据:

  • 月均 P1 故障从 3.2 次降到 1.1 次。
  • 产品与工程团队的争执减少——“Error Budget 说了算”成为共识。
  • 发布频率从每周 1 次增加到每周 3 次(因为每次发布的 Budget 消耗降低了,得益于更完善的灰度发布机制)。
  • 工程师对告警的响应速度提升——因为告警噪声减少了 70%,每一条告警都是有意义的。

九、SLO 的常见误区

误区一:SLO 越高越好

99.99% 听起来比 99.9% “好”,但它意味着 10 倍的成本和 10 倍的运维压力。大多数业务不需要四个九。一个内部管理系统的 SLO 设为 99.99% 是资源浪费。

误区二:SLO = SLA

SLO 是内部目标,SLA 是外部承诺。它们的受众、后果和设定逻辑完全不同。把 SLO 和 SLA 设为同一个值,意味着你没有安全边际——SLO 刚被突破就要赔钱。

误区三:只关注可用性

很多团队只设了可用性 SLO,忽略了延迟 SLO。一个可用性 99.99% 但 p99 延迟 10 秒的系统,用户体验并不好。可用性和延迟应该成对出现。

误区四:SLO 定了就不改

SLO 应该是一个活文档(Living Document)。业务变化了(用户量翻倍)、架构变化了(从单体拆成微服务)、用户期望变化了——SLO 都需要相应调整。建议每季度 Review 一次 SLO 的合理性。

误区五:忽视依赖链

你的服务依赖数据库、缓存、消息队列、第三方 API。每个依赖都有自己的可靠性上限。如果你的数据库 SLA 是 99.95%,你的服务 SLO 就不可能比 99.95% 更高(除非你有完善的降级方案)。设定 SLO 时,必须考虑整个依赖链的可靠性。


十、SLO 工程的权衡

维度 没有 SLO SLO 过于宽松 SLO 合理 SLO 过于严格
稳定性管理 靠感觉 形同虚设 数据驱动 过度保守
产品迭代速度 不可预测 无约束 有节奏 接近停滞
告警噪声 高(随意设阈值) 低(几乎不告警) 低(有意义的告警) 极高(频繁告警)
工程师体验 疲于救火 缺乏挑战 专注 疲于奔命
故障复盘 凭感觉分级 缺乏标准 Budget 驱动的分级 过度复盘
成本 低(无额外投入) 中(可观测性投入) 高(冗余和容灾投入)
组织信任 中(团队压力大)
适用阶段 早期探索 不推荐 成长期和成熟期 极端关键系统

十一、结论

SLO 工程的核心不是设定一个数字,而是围绕这个数字建立一套决策机制:

  1. 选择正确的 SLI——度量用户真正关心的指标,在靠近用户的位置度量。
  2. 设定合理的 SLO——不太紧(杀死迭代),不太松(形同虚设),基于历史数据和业务需求。
  3. 实施 Error Budget 策略——把”稳定性 vs. 功能开发”从主观争论变成量化决策。
  4. 建设多窗口燃烧率告警——减少告警噪声,提高告警质量。
  5. 让 SLO 驱动架构决策——缓存要不要加、服务要不要拆、数据库怎么选——都可以用 SLO 来量化评估。

SLO 不是银弹。它不能阻止故障发生,也不能自动修复 Bug。但它提供了一个共同语言,让产品、工程、管理层在”可靠性应该是多少”这个问题上达成共识。在大多数团队中,这个共识的价值远大于任何单一技术改进。


导航

上一篇:容灾架构:多活与灾备设计

下一篇:容量规划:从拍脑袋到数据驱动


参考资料

书籍

  • Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy, “Site Reliability Engineering: How Google Runs Production Systems”, O’Reilly, 2016. SRE 的开创性著作,第四章详细论述了 SLI/SLO/SLA 的定义和实践。
  • Betsy Beyer, Niall Richard Murphy, David K. Rensin, Kent Kawahara, Stephen Thorne, “The Site Reliability Workbook”, O’Reilly, 2018. 第二章和第五章给出了多窗口燃烧率告警的完整推导。
  • Alex Hidalgo, “Implementing Service Level Objectives”, O’Reilly, 2020. 目前关于 SLO 实施最完整的专著。

论文与博客

  • Google Cloud Blog, “SRE fundamentals: SLIs, SLAs and SLOs”, 2018. SLI/SLO/SLA 关系的简明解释。
  • Google Cloud Blog, “Alerting on SLOs like Pros”, 2020. 多窗口燃烧率告警的工程实践细节。
  • Will Larson, “Setting SLOs”, Irrational Exuberance Blog, 2021. 关于如何在工程组织中推动 SLO 采纳的实操建议。

工具

  • Prometheus 官方文档, “Recording Rules”. 预聚合规则的详细语法和最佳实践。
  • Grafana Labs, “SLO Monitoring and Alerting with Grafana”, 2022. 基于 Grafana 的 SLO Dashboard 模板和告警配置指南。
  • Sloth: GitHub 仓库(slok/sloth),基于 Prometheus 的 SLO 生成工具,自动生成燃烧率告警规则。
  • OpenSLO: GitHub 仓库(openslo/openslo),SLO 定义的开放标准,支持多种可观测性后端。

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-13 · architecture

【系统架构设计】告警策略:如何避免"狼来了"

大多数团队的告警系统都在制造噪声而不是传递信号。阈值告警看似直观,实则产生大量误报和漏报,值班工程师在凌晨三点被叫醒,却发现只是一次无害的毛刺。本文从告警疲劳的工业数据出发,拆解基于 SLO 的多窗口燃烧率告警算法,深入 Alertmanager 的路由、抑制与分组机制,结合 PagerDuty 的告警疲劳研究和真实工程案例,给出一套可落地的告警策略设计方法。

2026-04-13 · architecture

【系统架构设计】故障排查方法论:从告警到根因的系统化路径

凌晨三点的告警响了,你打开笔记本,盯着一堆指标不知道从哪里下手——两小时后发现是配置改错了。这种经历几乎每个 oncall 工程师都有过。本文从 Incident Command System 在 SRE 中的适配讲起,拆解从告警到根因的系统化排查路径,覆盖事件分级、假设驱动调试、事后复盘的无责文化、Google 与 Meta 的 oncall 体系,给出可落地的 Runbook 模板和 Postmortem 模板。

2026-04-22 · architecture / observability

【可观测性工程】指标体系设计:USE、RED、Golden Signals 与业务 KPI

USE 方法论适用于资源,RED 方法论适用于请求,Golden Signals 适用于服务——三套方法论各有其适用对象。本文从 Brendan Gregg、Tom Wilkie、Google SRE 的原始定义出发,构建覆盖资源→服务→业务的完整指标体系,并给出 Prometheus 命名规范、基数治理策略与可抄的指标清单。

2026-04-22 · architecture / observability

可观测性工程

从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。