2. SLI 指标深度解析:定义、类型与采集计算

SLI(Service Level Indicator,服务等级指标)是 SLO 体系的基石。没有准确、可量化的 SLI,SLO 就失去了衡量依据,自动降级更是无从谈起。本节将深入剖析 SLI 的定义方法、四大核心类型以及从采集到聚合计算的完整链路。

2.1 SLI 定义方法:从用户视角出发

定义 SLI 的核心原则是以用户为中心。指标必须反映用户实际感知的服务质量,而非内部技术细节。通常采用以下四步法:

  1. 确定用户关键行为:识别用户最常执行且对业务价值影响最大的操作(如登录、搜索、下单、播放视频)。
  2. 划定服务边界:明确指标覆盖的范围,是客户端到端(E2E)、API 网关层,还是后端服务层。
  3. 选择可测量属性:从延迟、错误、吞吐量、饱和度四个维度中选择最能反映该行为健康度的属性。
  4. 定义良好事件:明确什么算一次“成功”或“有效”的请求,排除爬虫、健康检查、预加载等非用户流量。
定义避坑:避免定义过于宽泛的 SLI(如“系统整体延迟”),应细化到具体 API 端点或业务操作。同时,确保 SLI 的采集成本可控,避免为了完美而引入无法持续维护的埋点。

2.2 四大核心 SLI 类型

业界公认的四大黄金信号(Golden Signals)构成了 SLI 的主体框架。下表对比了各类型的关注点、典型指标与采集方式:

SLI 类型 关注点 典型指标 采集方式
延迟 服务响应速度 P50 / P95 / P99 延迟(ms) 请求耗时埋点、APM 探针
错误率 请求失败比例 HTTP 5xx 率、超时率、业务错误码率 响应状态码统计、日志解析
吞吐量 系统处理能力 RPS(每秒请求数)、QPS(每秒查询数)、TPS(每秒事务数) 负载均衡器指标、服务端计数器
饱和度 资源耗尽程度 CPU 使用率、内存使用率、连接池占用率、磁盘 I/O 等待 系统监控 Agent、中间件暴露指标

2.2.1 延迟(Latency)

延迟是用户体验最直接的体现。通常使用百分位数而非平均值来衡量,因为平均值会掩盖长尾请求。例如,P99 延迟为 200ms 意味着 99% 的请求在 200ms 内完成,而 1% 的慢请求可能正是用户流失的关键。

2.2.2 错误率(Error Rate)

错误率不仅包括 HTTP 5xx 服务端错误,还应涵盖业务逻辑错误(如“库存不足”、“余额不足”返回的 4xx 状态码)。定义 SLI 时需明确哪些错误码计入“失败”事件。

2.2.3 吞吐量(Throughput)

吞吐量反映系统的负载水平。当吞吐量接近系统上限时,延迟和错误率往往会急剧恶化。吞吐量 SLI 通常与容量规划、自动扩缩容策略联动。

2.2.4 饱和度(Saturation)

饱和度是预测性指标,用于提前发现瓶颈。例如,数据库连接池使用率达到 80% 时,即使当前延迟正常,也应触发预警。饱和度 SLI 是自动降级决策的重要前置信号。

黄金信号联动示例:当吞吐量(RPS)突然飙升,导致 CPU 饱和度超过 90%,进而引发 P99 延迟从 100ms 暴涨至 2s,最终错误率从 0.1% 攀升至 5%。此时,基于饱和度和延迟的 SLI 波动,应触发自动降级策略,例如限流或降级非核心功能。

2.3 SLI 采集与计算

SLI 的采集与计算链路通常分为三个环节:数据采集 → 指标聚合 → 窗口计算。

2.3.1 数据采集方式

  • 埋点/探针:在应用代码中插入 SDK(如 OpenTelemetry),采集请求开始/结束时间、状态码、自定义业务标签。
  • 日志解析:从结构化日志(JSON 格式)中提取延迟、错误码等字段,通过 Logstash/Fluentd 等工具汇聚。
  • 指标暴露:服务通过 Prometheus 客户端库暴露 /metrics 端点,或通过 StatsD 协议推送指标。
  • 基础设施 Agent:Node Exporter、cAdvisor 等采集 CPU、内存、磁盘等系统级饱和度指标。

2.3.2 指标聚合与计算

原始数据需要经过聚合才能形成有意义的 SLI。以下是典型的计算逻辑示例:

# 示例:计算过去 5 分钟的错误率 SLI
# 假设指标:requests_total{status="200|500|..."} 和 errors_total{status="500|timeout"}

# PromQL 查询
rate(errors_total[5m]) / rate(requests_total[5m]) * 100

# 输出:过去 5 分钟的平均错误率百分比

对于延迟 SLI,通常使用直方图(Histogram)数据结构,在采集端预先分桶(Bucket),服务端计算百分位数:

# 示例:计算 P99 延迟
# 假设指标:http_request_duration_seconds_bucket{le="0.1|0.5|1|2|5|+Inf"}

# PromQL 查询
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

# 输出:过去 5 分钟内请求延迟的 P99 值(单位:秒)

2.3.3 窗口与滚动周期

SLI 计算需要定义时间窗口。常见窗口策略包括:

  • 固定窗口:如每分钟、每 5 分钟计算一次,简单但边界效应明显。
  • 滚动窗口:如过去 5 分钟、过去 1 小时,平滑度更好,是 SLO 计算的主流方式。
  • 指数加权移动平均(EWMA):对近期数据赋予更高权重,适合快速检测异常波动。
采集计算常见陷阱:
  • 忽略采样偏差:仅对部分请求采样会导致 SLI 失真,尤其对低概率的高延迟事件。
  • 时间戳对齐问题:跨服务调用时,各系统时钟不同步会导致延迟计算出现负值或异常大值。
  • 聚合粒度丢失:在计算 P99 时,如果直方图桶(Bucket)划分过粗,会导致百分位数精度下降。

2.4 SLI 采集与计算架构图

下图展示了从用户请求到 SLI 指标输出的完整数据流,涵盖采集、聚合、存储与查询四个阶段:

SLI 采集与计算架构 SLI 采集与计算架构 应用埋点 / SDK 日志解析 / Agent 基础设施 Exporter 采集层 采集层 采集层 指标聚合器(Prometheus Server / Metrics Pipeline) 时序数据库(TSDB) / 日志存储 SLI 计算引擎(PromQL / SQL) 输出:SLI 时间序列

2.5 SLI 定义与计算决策树

在实际工作中,定义 SLI 时经常面临多种选择。下面的决策树可以帮助团队快速确定合适的 SLI 类型与计算方式:

SLI 定义与计算决策树 SLI 定义与计算决策树 用户关键行为是什么? 响应时间敏感? 延迟 SLI:P99 延迟 SLI:P50 请求失败可枚举? 错误率 SLI:5xx+业务码 错误率 SLI:仅 5xx 容量/资源瓶颈? 吞吐量 SLI:RPS 饱和度 SLI:CPU/连接池 提示:一个行为可同时定义多个 SLI, 例如“下单”同时关注延迟、错误率和吞吐量。

2.6 小结:SLI 定义清单

在进入下一章 SLO 配置之前,请确保每个 SLI 都经过以下检查:

  • 用户视角:指标是否直接反映用户可感知的服务质量?
  • 可测量:是否有成熟的采集手段,且采集成本在可接受范围内?
  • 可区分:良好事件与不良事件的定义是否清晰无歧义?
  • 可聚合:指标是否支持按时间窗口、标签维度进行灵活聚合计算?
  • 可预警:SLI 的波动是否能够及时触发后续的 SLO 评估与降级动作?
实践建议:初期从 2-3 个核心用户行为开始,每个行为定义 1-2 个 SLI(如延迟 + 错误率)。随着可观测性成熟度提升,再逐步补充吞吐量和饱和度指标,最终形成完整的 SLI 矩阵。