3. SLO 基础:服务等级目标 (SLO) 定义、SLI 与 SLO 的关系、常见的 SLO 指标类型

在构建自动化发布策略之前,必须建立一套可量化的服务质量衡量体系。SLO(Service Level Objective,服务等级目标)正是这套体系的核心决策依据。它不是一个模糊的“系统要稳定”,而是一个精确的、可验证的数值承诺,直接决定了你的部署流水线何时可以放行、何时必须熔断。

3.1 核心概念:SLI、SLO 与 SLA 的三角关系

理解 SLO 的前提是区分三个经常被混用的术语:SLI(服务等级指标)、SLO(服务等级目标)和 SLA(服务等级协议)。它们构成了从测量到承诺的完整链路。

术语 定义 典型示例 责任主体
SLI 对服务某个维度的实际测量值,是原始数据 过去 5 分钟 P99 延迟 = 210ms 监控系统
SLO 对 SLI 设定的目标阈值,是内部承诺 月度 P99 延迟 ≤ 200ms 的比例 ≥ 99.9% 服务团队
SLA 对客户公开的法律承诺,通常附带赔偿条款 月度可用性 ≥ 99.99%,否则退还 10% 月费 法务 / 业务
关键原则:SLO 必须比 SLA 更严格。如果 SLA 承诺 99.99% 可用性,SLO 应设为 99.995%,预留出错误预算消耗的缓冲空间。SLO 是工程团队的内部驾驶仪表盘,SLA 是面向客户的法律红线。

3.2 SLI 与 SLO 的关系:测量与承诺的闭环

SLI 是“事实”,SLO 是“标准”。两者通过错误预算机制形成闭环:SLI 持续上报,SLO 定义可容忍的失效边界,超出边界的部分即为消耗的错误预算。当错误预算耗尽,部署频率必须降低或暂停。

SLI → SLO → 错误预算 → 部署决策 闭环 SLI 测量 延迟 / 错误率 / 吞吐 SLO 目标 99.9% 请求 ≤ 200ms 错误预算 剩余 0.1% 失效额度 定义阈值 计算消耗 部署决策 放行 / 熔断 / 回滚 预算耗尽 → 熔断 发布后持续观测 SLI 💡 闭环逻辑: SLI 持续上报 → 与 SLO 对比 → 消耗错误预算 → 预算状态驱动部署流水线决策 → 新版本上线后继续观测 SLI。
实践建议:在服务目录中为每个服务至少定义 2 个 SLO(延迟 + 可用性),并将错误预算剩余比例作为部署流水线的准入门禁。当错误预算低于 50% 时,自动降低部署频率;低于 20% 时,自动阻断非紧急发布。

3.3 常见的 SLO 指标类型

并非所有指标都适合作为 SLO。好的 SLO 指标必须满足三个条件:用户可感知、可精确测量、可设定合理阈值。以下是生产环境中使用最广泛的四类指标。

3.3.1 可用性 (Availability)

衡量服务是否正常响应请求。通常以“成功请求占总请求的百分比”来定义。对于有状态服务,还需考虑会话连续性。

  • 计算公式: (总请求数 - 失败请求数) / 总请求数 × 100%
  • 典型 SLO: 月度可用性 ≥ 99.99%
  • 常见陷阱: 仅监控 HTTP 状态码 5xx,忽略了业务逻辑错误(如返回 200 但实际数据错误)。

3.3.2 延迟 (Latency)

衡量请求从发出到收到完整响应的时间。由于延迟分布通常呈长尾特征,必须使用百分位值而非平均值。

  • 关键百分位: P50(中位数)、P95、P99(尾部延迟)。
  • 典型 SLO: P99 延迟 ≤ 200ms,且月度达标率 ≥ 99.9%
  • 常见陷阱: 只监控 P50 而忽略 P99,导致长尾延迟被掩盖。

3.3.3 吞吐量 (Throughput)

衡量服务在单位时间内处理的请求量。对于弹性伸缩和容量规划至关重要。

  • 计算公式: 请求总数 / 时间窗口(通常为 1 分钟)
  • 典型 SLO: 每分钟处理请求数 ≥ 10,000 RPS
  • 常见陷阱: 吞吐量 SLO 必须与延迟 SLO 联合使用,避免“高吞吐但高延迟”的虚假繁荣。

3.3.4 错误率 (Error Rate)

衡量请求失败的比例。失败不仅包括 HTTP 5xx,还应包括业务错误码、超时、熔断等。

  • 计算公式: 错误请求数 / 总请求数 × 100%
  • 典型 SLO: 错误率 ≤ 0.1%
  • 常见陷阱: 忽略客户端错误(4xx)中的业务异常,如“库存不足”返回 400 但实际是服务逻辑问题。

3.4 指标类型对比与选择策略

不同服务类型对指标的敏感度不同。下表总结了四类指标在不同场景下的优先级。

服务类型 首选指标 次选指标 说明
API 网关 / 微服务 延迟 (P99) 错误率 用户体验直接受响应速度影响
数据库 / 缓存 可用性 吞吐量 数据层必须持续可读写
消息队列 / 流处理 吞吐量 延迟 (P50) 关注处理能力而非单条速度
CDN / 静态资源 可用性 延迟 (P95) 全球多节点可用性优先
批处理 / 离线任务 错误率 吞吐量 关注数据完整性和完成度
避坑指南:不要试图为每个指标都设定 SLO。一个服务通常 2~3 个 SLO 就足够。过多的 SLO 会导致错误预算碎片化,团队无法聚焦真正的用户关键路径。在服务目录中,每个服务条目应明确标注其“黄金信号”指标。

3.5 定义 SLO 的实操步骤

在服务目录中为每个服务定义 SLO 时,建议遵循以下四步流程:

  1. 识别用户旅程: 列出该服务对外提供的关键 API 或功能点,例如“用户登录”、“商品搜索”、“订单提交”。
  2. 选择黄金信号: 从延迟、可用性、错误率、吞吐量中选出 2~3 个与用户体验最相关的指标作为 SLI。
  3. 设定初始阈值: 基于过去 1~3 个月的历史数据,取 P99 或 P95 值作为初始 SLO 阈值。如果没有历史数据,先设定一个宽松值(如 99.9%),后续逐步收紧。
  4. 定义时间窗口: 决定 SLO 的评估周期。常见窗口有:滚动 30 天、滚动 7 天、日历月度。滚动窗口更适合自动化发布策略,因为它能平滑处理突发波动。
服务目录 SLO 定义四步流程 ① 识别用户旅程 登录 / 搜索 / 下单 ② 选择黄金信号 延迟 + 错误率 ③ 设定初始阈值 P99 ≤ 200ms ④ 定义窗口 滚动 30 天 📌 服务目录集成: 每步产出的结果(用户旅程列表、SLI 定义、阈值、窗口)都应写入服务目录的 YAML 配置中, 作为自动化发布策略的元数据输入。后续章节将展示如何将这些 SLO 配置直接驱动部署流水线。

3.6 常见 SLO 定义示例(服务目录 YAML 片段)

以下是一个服务目录中 SLO 配置的 YAML 示例,展示了如何将上述概念落地为机器可读的配置。

# service-catalog/checkout-service/slo.yaml
apiVersion: catalog.slo/v1
kind: ServiceSLO
metadata:
  name: checkout-service-slo
  service: checkout-service
spec:
  # 可用性 SLO
  - name: availability
    sli:
      type: availability
      measurement: "successful_requests / total_requests"
      dataSource: prometheus
      query: 'sum(rate(http_requests_total{service="checkout",status!~"5.."}[5m])) / sum(rate(http_requests_total{service="checkout"}[5m]))'
    target:
      threshold: 99.99
      unit: percent
      window: rolling_30d
    errorBudget:
      initial: 0.01  # 1 - 0.9999 = 0.0001 = 0.01%
  
  # 延迟 SLO
  - name: latency-p99
    sli:
      type: latency
      percentile: 99
      dataSource: prometheus
      query: 'histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) by (le))'
    target:
      threshold: 200
      unit: ms
      window: rolling_7d
    errorBudget:
      initial: 0.1  # 允许 0.1% 的请求超过 200ms
自动化触发点:当 CI/CD 流水线读取到上述 SLO 配置时,会自动计算当前错误预算消耗。如果 errorBudget.remaining < 20%,流水线将阻断本次部署,并通知 SRE 团队。这个逻辑将在第 5 章“错误预算驱动的部署门禁”中详细实现。