4. SLI 聚合方式:平均值、百分位数(P50/P90/P99)、速率、分布对比
SLI(Service Level Indicator)的原始数据通常是一系列离散的测量点,例如单次请求的延迟、单次健康检查的结果。为了将这些原始数据转化为可度量、可报警的指标,必须选择一种聚合方式。不同的聚合方式会从不同角度刻画系统行为,直接影响异常检测的灵敏度和误报率。
本节将深入对比四种最常用的 SLI 聚合方式:平均值、百分位数(P50/P90/P99)、速率和分布,并给出在异常检测校准中的选型建议。
4.1 聚合方式核心对比
| 聚合方式 | 数学定义 | 对异常敏感度 | 信息损失程度 | 典型 SLI 场景 |
|---|---|---|---|---|
| 平均值 (Avg) | 总和 / 样本数 | 低(易被长尾稀释) | 高(掩盖离群点) | CPU 使用率、内存占用 |
| 百分位数 (P50/P90/P99) | 排序后第 p% 位置的值 | 高(P99 对极端值敏感) | 中(保留尾部信息) | 请求延迟、响应时间 |
| 速率 (Rate) | 单位时间事件计数 | 中(对突增/突降敏感) | 中(丢失单次质量) | QPS、错误率、吞吐量 |
| 分布 (Histogram) | 按桶计数的频率分布 | 极高(可检测多模态) | 低(保留完整形状) | 延迟分布、请求大小分布 |
校准提示: 在异常检测中,平均值是最不推荐用于延迟类 SLI 的聚合方式。一个 1% 的慢请求(10s)可以将 99% 的正常请求(100ms)的平均值拉高到约 200ms,导致检测器对“大多数用户”的真实体验失明。
4.2 四种聚合方式详解
4.2.1 平均值 (Average)
平均值计算简单,资源开销低,适合对同质性较高的指标进行聚合,例如集群中所有节点的 CPU 使用率。但在长尾分布(如延迟)中,平均值会严重偏离典型体验。
- 异常检测适用性: 仅适用于指标值分布接近正态或均匀的场景。
- 基线阈值设定: 通常使用
mean ± k * stddev,但需注意标准差本身也可能被异常值污染。 - 避坑: 不要用平均值定义延迟 SLO,否则 99% 的请求达标,但 SLO 可能显示已破线。
4.2.2 百分位数 (Percentile: P50/P90/P99)
百分位数通过排序直接反映“大多数用户”或“最差用户”的体验。P50(中位数)代表典型体验,P99 代表长尾中的最差体验。
- P50: 对异常不敏感,适合作为长期趋势基线。
- P90: 折中指标,常用于内部 SLO 监控。
- P99: 对极端值非常敏感,是异常检测的“放大镜”。
计算成本警告: 精确计算 P99 需要维护全量排序数据,在分布式系统中开销极大。生产环境通常使用 T-Digest 或 HDR Histogram 等近似算法,这会引入 1%-5% 的误差,校准基线时需预留余量。
4.2.3 速率 (Rate)
速率描述事件发生的频率,通常通过 rate() 或 irate() 函数计算(如 Prometheus)。它天然适合检测突增(流量高峰)和突降(服务宕机)。
- 错误率:
rate(errors_total[5m]) / rate(requests_total[5m]),是黄金信号之一。 - 吞吐量:
rate(bytes_sent_total[1m]),用于容量规划。 - 异常检测特点: 速率指标通常呈现季节性周期,适合使用“同比”或“环比”基线。
4.2.4 分布 (Distribution / Histogram)
分布聚合不丢失数据形状,通过多个桶(Bucket)记录落在不同区间的计数。它是可观测性数据最完整的形态,但存储和计算成本最高。
- 优势: 可以同时计算 P50、P90、P99,甚至检测双峰分布(如缓存命中与未命中的延迟差异)。
- 异常检测: 可以检测“分布漂移”,例如原本集中在 100ms 的延迟,突然出现第二个峰在 1s。
- 实现: Prometheus Histogram、OpenTelemetry 的 Exponential Histogram。
4.3 聚合方式选型决策流程
下图展示了在 SLI 设计阶段,如何根据指标特性和检测目标选择合适的聚合方式。
4.4 聚合方式对异常检测基线的影响
不同的聚合方式直接决定了基线阈值(如动态阈值、静态阈值)的设定方法。下表总结了四种聚合方式在基线校准中的关键差异。
| 聚合方式 | 基线模型建议 | 对季节性敏感度 | 异常检测算法推荐 |
|---|---|---|---|
| 平均值 | 简单移动平均 (SMA) 或指数加权移动平均 (EWMA) | 低(需手动去除趋势) | 3-sigma、CUSUM |
| 百分位数 (P99) | 分位数回归或基于窗口的滚动分位数 | 中(需较大窗口平滑) | Seasonal-Trend Decomposition (STL) + 残差检测 |
| 速率 | 同比/环比基线(同一天同一时刻) | 高(必须对齐时间周期) | Prophet、异常检测 ETS |
| 分布 | 分布距离度量(如 Jensen-Shannon 散度) | 高(需逐桶建模) | 基于直方图的马氏距离、PCA 异常检测 |
实践建议: 在构建 SLI 基线时,不要只依赖单一聚合方式。推荐采用“分层聚合”策略:
1. 使用 分布 或 P99 作为“高灵敏度”检测层,快速发现尾部异常。
2. 使用 速率 作为“容量”检测层,发现流量突增或突降。
3. 使用 平均值 作为“长期趋势”参考层,辅助根因分析。
1. 使用 分布 或 P99 作为“高灵敏度”检测层,快速发现尾部异常。
2. 使用 速率 作为“容量”检测层,发现流量突增或突降。
3. 使用 平均值 作为“长期趋势”参考层,辅助根因分析。
4.5 案例:延迟 SLI 的聚合选择
假设某 API 服务的延迟数据如下(单位 ms):
原始样本: [95, 100, 102, 98, 105, 110, 99, 101, 97, 3000, 4500]
样本数: 11
不同聚合方式的结果差异巨大:
- 平均值: (95+100+...+4500)/11 ≈ 800ms。这个值不能代表任何真实用户。
- P50(中位数): 排序后第6个值 = 100ms。代表典型用户。
- P99: 排序后第11个值 ≈ 4500ms。代表最差用户。
- 速率: 不适用,因为延迟不是计数指标。
- 分布: 可以清晰看到两个峰:一个在 95-110ms 区间,一个在 3000-4500ms 区间。
如果使用平均值设定基线阈值(如 avg + 3*stddev),阈值会被拉高到约 2000ms,导致 4500ms 的极端异常被判定为正常。而使用 P99 基线,可以直接对 4500ms 触发报警。
关键结论: 对于延迟类 SLI,永远不要使用平均值作为异常检测的输入。优先选择 P99 或分布聚合。如果存储成本受限,至少使用 P90 作为折中方案。