• 作者:老汪软件技巧
  • 发表时间:2024-12-04 04:02
  • 浏览量:

Prometheus已经成为可观测领域指标领域最常用的技术。

一、了解时序数据

指标是以时序数据(Time Series)的方式表达的,什么是时序数据呢?

我们以Prometheus采集机器cpu指标示例:

node_cpu_seconds_total{cpu="0", mode="user", instance="192.168.1.10:9100"} 1345.67 1701409200000
node_cpu_seconds_total{cpu="0", mode="system", instance="192.168.1.10:9100"} 2345.89 1701409200000

上面展示了Prometheus时序数据的数据结构:

而时序库(Time series database)就是一种专门处理时序数据的数据库,其中InfluxDB、Prometheus、VictoriaMetrics、M3DB 等都是时序库。

二、时序数据类型

Prometheus 支持4数据类型,分为 Gauge、Counter、Histogram、Summary。

1. Counter(计数器)定义

Counter 是一种只能递增的指标数据类型,用于表示累积值。计数器只能在特定情况下(如系统重启或数据重置时)归零,不能减少。

用途

适用于累计量统计场景,例如:

数据结构

计数器的值随着时间递增,例如:

http_requests_total{method="GET", status="200"} 1024 1701409200000
http_requests_total{method="POST", status="500"} 10 1701409200000

上述数据表示:

使用示例

在 PromQL 查询中,可以通过 rate() 或 increase() 函数计算计数器的增长速率或增加量。例如:

rate(http_requests_total[5m])

increase(http_requests_total[5m])

2. Gauge(仪表盘)定义

Gauge 是一种可以任意增加或减少的指标数据类型,通常用于表示瞬时值,例如系统状态或资源使用情况。

用途

适用于描述当前状态的场景,例如:

数据结构

Gauge 的值随时间波动,例如:

node_memory_available_bytes{instance="192.168.1.10:9100"} 1048576000 1701409200000
node_cpu_usage_percentage{instance="192.168.1.10:9100"} 75.5 1701409200000

上述数据表示:

使用示例

查询当前的瞬时值:

node_memory_available_bytes

计算过去 5 分钟的平均值:

avg_over_time(node_cpu_usage_percentage[5m])

3. Histogram(直方图)定义

Histogram 将数据分布到多个桶中,用于统计数据的分布范围,例如响应时间或延迟。Histogram 指标通常伴随以下三个子指标:

_bucket:表示落在每个桶范围内的样本数;_count:样本总数;_sum:样本值的总和。用途

适用于数据分布分析场景,例如:

数据结构

假设我们需要统计请求延迟:

plaintext
http_request_duration_seconds_bucket{le="0.1"} 2400 1701409200000
http_request_duration_seconds_bucket{le="0.5"} 5000 1701409200000
http_request_duration_seconds_bucket{le="1.0"} 7500 1701409200000
http_request_duration_seconds_bucket{le="+Inf"} 10000 1701409200000

_监控指标是什么意思_监控器指标

http_request_duration_seconds_count 10000 1701409200000 http_request_duration_seconds_sum 7200 1701409200000

上述数据表示:

使用示例

rate(http_request_duration_seconds_bucket[5m])

rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])

4. Summary(摘要)定义

Summary 是对数据的统计摘要,直接提供分位数(Quantile)值,例如中位数(50% 分位数)、90% 分位数、99% 分位数等。

用途

适用于单实例的统计场景,例如:

数据结构

假设我们需要统计请求延迟的分位数:

http_request_duration_seconds{quantile="0.5"} 0.3
http_request_duration_seconds{quantile="0.9"} 0.8
http_request_duration_seconds{quantile="0.99"} 1.2

上述数据表示:

使用示例

http_request_duration_seconds{quantile="0.5"}

Histogram 与 Summary 的对比5.1 简单比较特点HistogramSummary

数据存储方式

分桶(_bucket)

提供分位数(quantile)

全局聚合能力

支持多实例聚合

不支持全局聚合

分位数计算

查询时由server端动态计算

client端预先计算好

适用场景

适合多实例场景,如全球延迟分布统计

适合单实例场景,如本地延迟摘要

5.2 如果要计算百分数,选Histogram 还是 Summary?

在实际使用时,笔者曾经使用Summary来计算百分数,例如计算方法、接口的请求耗时P50、P90的值,但是最终发现,还是Histogram更加适合,下面是Histogram 还是 Summary选型对比。

维度HistogramSummary

百分位计算方式

百分位数由桶区间和数据分布推导而来,精度依赖桶设计。

百分位数由客户端直接计算,精度高且不受分布影响。

动态分布适配性

若分布变化大(如计算方法的耗时,不同方法的耗时从 100ms 到 20000ms,且不同方法的耗时集中在不同区间),此时则需更多桶支持,增加存储和计算开销。

不依赖桶设计,无需调整参数,能直接适应动态分布,始终保持高精度。

多实例聚合能力

支持多实例和跨指标聚合(如 sum、avg),适合多节点大规模监控。

不支持跨实例聚合,主要适合单实例监控。例如,实例A的P99值为100,实例B的P99值为1000,如果要将聚合计算两个实例P99值,则无法计算出相对准确的结果值。即不管是用avg,还是max等方式,结果都很不准确。

计算资源消耗

服务端依赖桶设计计算百分位,若桶多,计算和存储开销较大。例如,为了能计算百分位值P50,P90,但不同区间的值分布有所差异(例如:第01:00,方法耗时大部分落在100-200ms,02:00落在3000-4000ms),这时桶就很不好设置,只能设置较多的bucket来应对。这种情况下如果设置比较多的bucket,导致时序数据数量非常多;而bucket太少或者颗粒度太粗,计算的百分位就会很不准确。

客户端直接计算百分位,服务端资源占用小,但客户端负载较高。

适用场景

适合需要多实例聚合、多指标关联分析场景,或对绝对精度要求较低的情况。

适合单实例、需要高精度百分位数分析的场景,尤其是分布动态变化较大的情况。

总结:

Summary适用于单实例,精度相比Histogram精度更准确,但是当前线上环境基本都是分布式多实例架构,而Summary不适用于多实例聚合计算,这是致命弱点。

在 最新 OpenTelemetry 协议标准 中,Summary 类型也已被明确标记为不推荐(deprecated)。

所以,对于绝大部分场景而言,Histogram比Summary更适合计算百分位,但需要注意,Histogram需要合理地设置桶的区间大小和数量,使得在可接受的存储、计算性能消耗下,计算出精度相对准确的百分位数。