3. SLI 指标设计原则:如何选择有效的 SLI
SLI(Service Level Indicator)是 SLO 的量化基础。选错 SLI,再复杂的异常检测也无法准确反映真实服务质量。本章聚焦黄金信号(Golden Signals)与 USE/RED 方法,给出可落地的 SLI 选择原则。
3.1 黄金信号:四大核心维度
Google SRE 团队提出的“黄金信号”是 SLI 设计的起点,涵盖延迟、错误率、吞吐量和饱和度。四个维度缺一不可,但并非每个服务都需要全部覆盖——应根据服务类型(在线、批处理、存储)裁剪。
| 维度 | 定义 | 典型 SLI 示例 | 采集来源(OTel) |
|---|---|---|---|
| 延迟 | 请求从发出到收到响应的时间 | p50 / p95 / p99 延迟 ≤ 200ms | http.server.duration / rpc.server.duration |
| 错误率 | 失败请求占总请求的比例 | HTTP 5xx 占比 ≤ 1% | http.server.request_count (status_code) |
| 吞吐量 | 系统每秒处理的请求数 | QPS ≥ 1000 | http.server.request_count (rate) |
| 饱和度 | 资源使用程度,越接近上限越危险 | CPU 使用率 ≤ 80% | process.runtime.jvm.cpu.utilization / system.cpu.utilization |
实践建议: 不要将四个信号全部设为 SLI。对于用户感知型服务,优先选择延迟和错误率;对于基础设施层,优先选择饱和度和吞吐量。
3.2 USE 方法:面向资源
USE(Utilization、Saturation、Errors)由 Brendan Gregg 提出,适用于硬件资源(CPU、内存、磁盘、网络)的可观测性。每个资源都从三个角度评估:
- 利用率(Utilization):资源被占用的平均比例。例如 CPU 利用率 70%,磁盘 I/O 利用率 60%。
- 饱和度(Saturation):资源排队或过载的程度。例如 CPU 运行队列长度、磁盘 I/O 等待队列。
- 错误(Errors):资源层面的错误计数。例如磁盘坏道、网络丢包、内存 ECC 错误。
USE 方法适用场景: 数据库节点、缓存集群、负载均衡器、物理机/虚拟机。不适合直接用于业务 API 或用户界面。
3.3 RED 方法:面向服务
RED(Rate、Errors、Duration)由 Tom Wilkie 提出,专为微服务和 API 设计。它将黄金信号简化为三个指标:
- 速率(Rate):每秒请求数(RPS),对应吞吐量。
- 错误(Errors):失败请求的比例或数。
- 持续时间(Duration):请求处理时间分布,对应延迟。
RED 方法省略了饱和度,因为服务层面的饱和度通常由下游资源(数据库、网络)体现,更适合在 USE 中处理。
| 对比维度 | USE 方法 | RED 方法 |
|---|---|---|
| 目标对象 | 基础设施资源 | 微服务 / API |
| 核心指标 | 利用率、饱和度、错误 | 速率、错误、持续时间 |
| 典型 SLI | CPU 利用率、磁盘队列长度 | QPS、错误率、p99 延迟 |
| 与 OTel 集成 | system.* / process.* metrics | http.* / rpc.* metrics |
| 异常检测重点 | 资源瓶颈预测 | 用户体验退化 |
3.4 SLI 选择原则:五条硬规则
- 用户视角优先:SLI 必须反映用户真实体验。例如,选择“页面加载时间”而非“服务器处理时间”。
- 可测量且可采集:SLI 必须能从 OTel 指标、日志或链路中稳定获取,避免依赖手工上报。
- 区分“好”与“坏”:每个 SLI 必须有明确的阈值或分布边界。例如“p99 延迟 ≤ 500ms”比“平均延迟”更有意义。
- 避免指标爆炸:每个服务选择 3~5 个 SLI 即可。过多 SLI 会导致 SLO 碎片化,异常检测噪声增大。
- 分层覆盖:基础设施层用 USE,服务层用 RED,业务层用黄金信号裁剪版。三层之间通过 OTel 的 Resource 属性关联。
常见陷阱: 不要将“CPU 利用率”直接作为用户请求的 SLI。CPU 高不一定代表用户体验差,可能是后台批处理任务导致。始终从用户请求链路出发选择 SLI。
3.5 从 SLI 到 SLO:阈值与分布
选定 SLI 后,需要定义“好事件”的标准。以延迟为例:
# OpenTelemetry 指标定义示例(Prometheus 格式)
# 延迟 SLI:http.server.duration
# 好事件:p99 延迟 < 200ms
# 坏事件:p99 延迟 >= 200ms
# 在 OTel Collector 中配置 Service Level Indicator
processors:
filter/sli:
metrics:
include:
match_type: regexp
metric_names:
- http.server.duration
transform/sli:
metric_statements:
- context: datapoint
statements:
- set(attributes["sli_type"], "latency")
- set(attributes["good"], gauge < 200000) # 200ms = 200000µs
上述配置将延迟数据标记为“好”或“坏”,后续 SLO 计算和异常检测直接基于此标签聚合。
3.6 实战:为电商下单服务选择 SLI
| 层级 | 方法 | SLI | 好事件标准 | OTel 指标 |
|---|---|---|---|---|
| API 网关 | RED | 下单请求延迟 | p95 ≤ 500ms | http.server.duration |
| 订单服务 | RED | 下单错误率 | HTTP 5xx < 0.5% | http.server.request_count |
| 数据库 | USE | 连接池饱和度 | 活跃连接 < 80% 最大连接 | db.client.connections.usage |
| 缓存 | USE | 缓存命中率 | 命中率 ≥ 90% | cache.hit.ratio |
关键结论: SLI 设计不是一次性工作。随着服务演进,SLI 需要定期复审。建议每季度结合 SLO 达成率和异常检测告警质量,调整 SLI 的阈值和分布边界。