3. SLI 采集与指标设计:如何定义有效的 SLI 指标,基于 RED 方法设计黄金信号

在可观测性体系中,SLI(Service Level Indicator,服务等级指标)是连接原始观测数据与 SLO 违约判定的桥梁。如果 SLI 定义不准确,后续的告警、追踪与 MTTR 复盘将失去根基。本章聚焦于如何基于 RED 方法(Rate、Errors、Duration) 设计黄金信号,确保每个 SLI 都能真实反映用户侧的服务质量。

3.1 为什么选择 RED 方法?

传统监控常陷入“指标爆炸”的困境——CPU、内存、磁盘、网络等基础设施指标堆积如山,却无法回答“服务是否正常”这一核心问题。RED 方法由 Tom Wilkie 提出,专为微服务与分布式系统设计,将指标收敛为三个维度:

维度 英文 核心含义 典型问题
Rate(速率) Rate 每秒请求数(RPS)或每分钟事务数 流量是否正常?是否存在突发或断崖?
Errors(错误) Errors 请求失败的数量或比例 错误率是否超过阈值?哪些接口在报错?
Duration(持续时间) Duration 请求响应时间(延迟分布) P50/P95/P99 延迟是否满足预期?
关键原则:RED 方法要求每个服务至少暴露 Rate、Errors、Duration 三个指标,且指标必须从用户请求的视角采集,而非从基础设施视角。

3.2 基于 RED 方法的 SLI 定义框架

定义 SLI 时,需要明确 指标名称、测量方式、聚合粒度 和 时间窗口。以下是一个标准化的 SLI 定义模板:

# 通用 SLI 定义模板
sli_name: "service_requests_total"
type: counter
labels:
  - service: "checkout-service"
  - endpoint: "/api/v1/checkout"
  - method: "POST"
  - status_code: "2xx|4xx|5xx"
measurement: "每秒请求数(RPS)"
aggregation: "1分钟窗口平均"

针对 RED 三个维度,我们分别给出具体的 SLI 设计示例:

3.2.1 Rate(速率)SLI

  • 指标名:http_requests_total(Counter 类型)
  • 标签:service、endpoint、method
  • 计算方式:rate(http_requests_total[1m])
  • 用途:检测流量异常(如突降表示服务不可用,突增表示可能遭受攻击或促销活动)

3.2.2 Errors(错误)SLI

  • 指标名:http_requests_errors_total(Counter 类型)
  • 标签:service、endpoint、error_code(如 500、503、timeout)
  • 计算方式:rate(http_requests_errors_total[1m]) / rate(http_requests_total[1m])
  • 用途:计算错误率,触发 SLO 违约告警的核心依据

3.2.3 Duration(持续时间)SLI

  • 指标名:http_request_duration_seconds(Histogram 类型)
  • 标签:service、endpoint、le(桶边界)
  • 计算方式:histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
  • 用途:获取 P99 延迟,判断长尾请求是否影响用户体验
实践建议:Duration 指标推荐使用 Histogram 而非 Summary。Histogram 支持服务端聚合与分位数计算,更适合分布式追踪场景下的全局延迟分析。

3.3 RED 黄金信号与分布式追踪的映射

在分布式追踪中,每个 Span 都携带了 RED 所需的信息。通过 OpenTelemetry 或 Jaeger 等工具,我们可以直接从 Trace 中提取 SLI:

RED 维度 Trace 字段 采集方式
Rate span_id 计数 统计每秒产生的 Root Span 数量
Errors status.code 统计 status.code = ERROR 的 Span 占比
Duration end_time - start_time 对 Span 持续时间进行分位数计算

下图展示了从 Trace 到 SLI 再到 SLO 的完整数据流:

从 Trace 到 SLI 再到 SLO 的数据流 Trace 数据源 Span / Root Span RED 指标提取 Rate / Errors / Duration SLI 时序存储 Prometheus / Cortex SLO 评估引擎 窗口滑动计算 违约告警 关键点 Trace 必须携带 status.code

3.4 SLI 设计中的常见陷阱与避坑指南

陷阱 1:使用平均值衡量 Duration。 平均延迟会掩盖长尾问题。例如 99% 请求 10ms,1% 请求 10s,平均值为 109ms,看似正常,实则 P99 已严重超标。正确做法:始终使用分位数(P50/P95/P99)。
陷阱 2:错误率只统计 HTTP 5xx。 业务错误(如“库存不足”返回 200)同样影响用户体验。正确做法:在应用层定义业务错误码,并纳入 Errors SLI。
陷阱 3:Rate 指标忽略健康检查流量。 健康检查请求会拉高 Rate,稀释真实用户流量。正确做法:通过标签过滤掉 /health、/metrics 等端点。

3.5 实战:为“订单服务”定义 RED 黄金信号

假设我们有一个 order-service,需要为其定义 SLI。以下是完整的指标设计清单:

SLI 名称 类型 PromQL 示例 SLO 目标
order_requests_rate Rate rate(order_requests_total[1m]) ≥ 100 RPS(基线)
order_error_ratio Errors rate(order_errors_total[1m]) / rate(order_requests_total[1m]) ≤ 0.1%
order_duration_p99 Duration histogram_quantile(0.99, rate(order_duration_seconds_bucket[5m])) ≤ 500ms
采集配置示例(OpenTelemetry Collector):
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  batch:
    timeout: 1s
  attributes:
    actions:
      - key: service.name
        value: "order-service"
        action: upsert

exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
    namespace: "sre"

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, attributes]
      exporters: [prometheus]

通过上述配置,Trace 数据中的 Span 持续时间、状态码等信息会被自动转换为 Prometheus 指标,进而支持 RED 黄金信号的实时计算。

3.6 小结:SLI 设计的三个黄金法则

  1. 用户视角优先:SLI 必须从用户请求的入口开始采集,而非从中间件或基础设施。
  2. RED 全覆盖:每个服务至少暴露 Rate、Errors、Duration 三类指标,缺一不可。
  3. 分位数与窗口:Duration 使用 P99/P95,错误率使用滑动窗口(如 5 分钟),避免瞬时抖动导致误告警。