SLA/SLO/SLI 与性能目标设定
「系统可用性 99.9%」——这句话到底意味着什么?一年有 525600 分钟,99.9% 意味着全年可以容忍约 525 分钟(约 8.7 小时)的不可用时间。但这 8.7 小时是连续的还是分散的?是计划内还是计划外的?这些问题,SLA/SLO/SLI 体系能够给你答案。
三者的定义与关系
SLA、SLO、SLI 是三个层层递进的概念:
flowchart LR
subgraph 定义
SLI["SLI\nService Level Indicator\n可量化的指标本身"]
SLO["SLO\nService Level Objective\n基于指标设定的目标"]
SLA["SLA\nService Level Agreement\n包含目标的正式协议"]
end
SLI --> |"是基础"| SLO
SLO --> |"是承诺"| SLA
style SLI fill:#e3f2fd
style SLO fill:#e8f5e8
style SLA fill:#fff3e0
SLI(Service Level Indicator) 是可量化的指标本身。比如「HTTP 请求的成功率」「接口的 TP99 延迟」「服务的启动时间」。SLI 是原始数据,是监控仪表盘上的数字。
SLO(Service Level Objective) 是基于 SLI 设定的目标。比如「HTTP 请求成功率 >= 99.9%」「TP99 延迟 < 200ms」。SLO 是承诺,是团队内部或对外的「达标线」。
SLA(Service Level Agreement) 是包含 SLO 的正式协议,通常有法律效力。SLA 会规定:如果 SLO 未达标,会有什么后果(比如赔偿、罚款)。SLA 是合同,是商业承诺。
三者的关系是:SLI 是事实,SLO 是目标,SLA 是承诺。没有 SLI,SLO 就是空话;没有 SLO,SLA 就是无本之木。
常用 SLI 指标
延迟类 SLI
- HTTP 请求延迟:TP50/TP90/TP99 延迟
- 首字节时间(TTFB):Time To First Byte
- DNS 解析时间:DNS lookup time
- SSL/TLS 握手时间:Connection setup time
可用性类 SLI
- 请求成功率:成功请求数 ÷ 总请求数
- 错误率:4xx/5xx 错误占比
- 服务可用时间:uptime ÷ (uptime + downtime)
吞吐量类 SLI
- QPS/RPS:每秒请求数
- TPS:每秒事务数
- 并发连接数:同时活跃的连接数
数据新鲜度类 SLI
- 数据同步延迟:主从数据同步的时间差
- 缓存命中率:缓存命中的请求占比
- 数据更新延迟:数据写入到可查询的时间
如何设定有效的 SLO
SLO 设定原则
SLO 不是越高越好,而是合理就好。设定 SLO 需要考虑以下因素:
- 用户期望:用户真正关心的指标是什么?
- 实现成本:达到更高 SLO 需要付出多少代价?
- 业务风险:SLO 不达标会造成多大的业务损失?
SLO 设定的漏斗模型
flowchart TD
subgraph 漏斗模型
A["用户期望\n用户认为可接受的水平"]
B["内部目标\n比用户期望略高"]
C["SLA 承诺\n基于历史数据设定"]
D["告警阈值\n触发告警的底线"]
end
A --> B --> C --> D
style A fill:#c8e6c9
style B fill:#fff9c4
style C fill:#ffe0b2
style D fill:#ffebee
SLO 计算示例
假设历史数据显示:
- 当前请求成功率:99.5%
- 最近 30 天有 2 次低于 99% 的时段
合理的 SLO 设定:
{
"slo_name": "api_success_rate",
"target": 0.999,
"window": "30d",
"measurement": "request_success_rate",
"filter": "uri starts with '/api/'"
}
避免 SLO 过度工程化
很多团队犯的错误是把 SLO 设得太高,导致:
- 永远达不到,团队失去信心
- 过度优化,投入产出比不合理
- 忽视其他重要指标
经验法则:SLO 应该比历史最佳表现低一些,留出改进空间。
错误预算概念
什么是错误预算
错误预算(Error Budget)是 SLO 的「另一半」。如果说 SLO 是「我们要达到的目标」,错误预算就是「我们还能承受多少失败」。
计算方式很简单:错误预算 = 100% - SLO。
如果 SLO 是 99.9%,错误预算就是 0.1%。换算成时间:
每月错误预算:30d × 24h × 60m × 0.1% = 43.8 分钟
每年错误预算:365d × 24h × 60m × 0.1% = 525.6 分钟 ≈ 8.76 小时
错误预算的用法
错误预算的用法是:用它来驱动发布决策。
gantt
title 错误预算消耗跟踪
dateFormat YYYY-MM-DD
section 错误预算
1月: 0, 31d
2月: 31, 28d
3月: 59, 31d
section SLO红线
75%消耗警戒: 0, 23d
100%完全消耗: 31, 31d
错误预算消耗策略:
- 错误预算充足时:可以正常发布新功能,冒烟测试即可
- 错误预算消耗到 75%:减少发布频率,加强测试
- 错误预算即将耗尽:暂停发布,专注稳定性
- 错误预算耗尽:冻结发布,快速修复问题
错误预算的误解
很多团队的误区是:把 SLO 当成最高目标,而不是最低标准。
SLO 是「我们承诺的最低水平」,不是「我们追求的最高水平」。如果团队总是踩着 SLO 线运行,说明 SLO 设置得太高了,或者团队根本没有提升空间。
另一个误区是:只关注 SLO,不关注错误预算。SLO 是目标,错误预算才是真正用来做决策的工具。
基于 SLO 的告警
告警策略
基于 SLO 的告警通常有多个级别:
flowchart TD
subgraph 告警级别
A["Burn Rate 告警\n错误预算消耗速率"]
B["多窗口告警\n短期 + 长期窗口"]
C["预算剩余告警\n剩余预算百分比"]
end
A --> |"短期高消耗| B
B --> |"持续高消耗| C
Burn Rate 概念
Burn Rate(燃烧速率)描述错误预算的消耗速度:
Burn Rate = 当前错误率 ÷ SLO 允许的错误率
例如:
- 当前错误率:0.5%
- SLO 目标:99.9%(允许 0.1% 错误)
- Burn Rate = 0.5% ÷ 0.1% = 5
解读:以当前速度,错误预算会在 1/5 的周期内耗尽
多窗口告警
单一时段的高错误率可能是噪声,长期累积的高错误率才是真正的问题:
// Prometheus SLO 告警规则
groups:
- name: slo-alerts
rules:
# 短期窗口(1小时),高速消耗
- alert: SLIHighErrorRateShort
expr: |
(sum(rate(http_requests_total{job="api",code=~"5.."}[5m]))
/ sum(rate(http_requests_total{job="api"}[5m]))) > 0.01
for: 2m
labels:
severity: warning
annotations:
summary: "SLI 短期错误率过高"
# 长期窗口(1天),持续消耗
- alert: SLOErrorBudgetBurn
expr: |
sum(rate(http_requests_total{job="api",code=~"5.."}[1h]))
/ sum(rate(http_requests_total{job="api"}[1h])) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "错误预算持续消耗"
SLO 驱动的监控
看板设计
SLO 驱动的监控看板应该展示:
flowchart LR
subgraph 监控看板
A["SLO 状态\n当前达标情况"]
B["错误预算\n剩余量与消耗速度"]
C["SLI 趋势\n指标随时间的变化"]
D["事件历史\n过去的问题与恢复"]
end
SLI 达标率计算
# 计算 SLI 达标率的伪代码
def calculate_sli_compliance(sli_data, slo_target, window):
"""
sli_data: SLI 指标数据点列表
slo_target: SLO 目标值(如 0.999)
window: 统计窗口(如 '30d')
"""
compliant_points = sum(1 for point in sli_data
if point.value >= slo_target)
total_points = len(sli_data)
compliance_rate = compliant_points / total_points
return compliance_rate
目标 vs 实际
graph LR
subgraph 目标 vs 实际
A["SLO 目标\n99.9%"] --> C["对比"]
B["SLI 实际\n99.95%"] --> C
C --> D["达标 ✓"]
end
真实案例:SLO 设定决策
案例背景
某电商平台的订单服务:
- 当前状态:请求成功率 99.5%,延迟 TP99 300ms
- 用户投诉:偶发订单失败,平均每天 2~3 次
- 业务影响:每次失败订单损失约 500 元
分析过程
- 用户期望调研:用户能接受的订单失败率是多少?
- 成本分析:提高 SLO 需要增加多少成本?
- 风险评估:SLO 不达标会造成多大损失?
决策
flowchart TD
subgraph 决策矩阵
A["选项 A:维持现状"]
B["选项 B:提升到 99.9%"]
C["选项 C:提升到 99.99%"]
end
subgraph 评估
D["当前损失:2~3 次/天 × 500 元 = 1000~1500 元/天"]
E["选项 B:需增加 10% 成本,损失降到 0.5 次/天"]
F["选项 C:需增加 50% 成本,损失降到 0.1 次/天"]
end
A --> D
B --> E
C --> F
最终决策:选项 B,在成本和收益之间取得平衡。
本章总结
核心要点:
- SLI 是事实:可量化的指标本身
- SLO 是目标:基于指标设定的达标线
- SLA 是承诺:包含目标的正式协议
- 错误预算 = 100% - SLO:用于驱动发布决策
- Burn Rate:描述错误预算的消耗速度
- SLO 不是越高越好:合理就好,考虑成本收益比
理解 SLA/SLO/SLI 是制定性能目标和建立监控体系的基础。下一节我们将讲解可用性与性能的关系。