写点什么

prometheus Histogram 统计原理

  • 2023-07-06
    广东
  • 本文字数:2188 字

    阅读完需:约 7 分钟

prometheus Histogram 统计原理

大家好,我是蓝胖子,书接上文,我在prometheus描点原理那一篇文章里,留了一个思考题:


我们通常会用到 histogram_quantile 去计算服务接口时间的耗时情况。


histogram_quantile(0.99,rate(server_handle_seconds_bucket{}[1m]))
复制代码


但是 rate 函数会将原指标按时间求斜率,这样会影响原本分位数的计算吗?


先说下结论,不影响分位数结果的计算。要解释这个问题,还是要看看分位数统计 Histogram 的原理。

Histogram 指标内容

在解释统计原理之前,我们先看看 Histogram 指标指标究竟是如何存储的,当我们用 prometheus 客户端创建一个 Histogram 监控数据类型时,其本质上会创建一组指标,如下所示:


注意概念,在 prometheus 中,如果指标名和标签完全相同,那么将会认为他们是同一个指标,将携带有时间戳的指标 称为指标的样本。prometheus server web 控制台查询出来的就是样本。


# TYPE server_handle_seconds histogramserver_handle_seconds_bucket{type="http",le="0.005"} 0server_handle_seconds_bucket{type="http",le="0.01"} 0server_handle_seconds_bucket{type="http",le="0.025"} 0server_handle_seconds_bucket{type="http",le="0.05"} 0server_handle_seconds_bucket{type="http",le="0.1"} 0server_handle_seconds_bucket{type="http",le="0.25"} 0server_handle_seconds_bucket{type="http",le="0.5"} 0server_handle_seconds_bucket{type="http",le="1"} 0server_handle_seconds_bucket{type="http",le="2.5"} 0server_handle_seconds_bucket{type="http",le="5"} 0server_handle_seconds_bucket{type="http",le="10"} 37092server_handle_seconds_bucket{type="http",le="+Inf"} 37092server_handle_seconds_sum{type="http"} 370920server_handle_seconds_count{type="http"} 37092
复制代码


le 标签可以认为是 Histogram 监控数据类型特有的标签,含义是桶的上边界, 拿上述指标 server_handle_seconds_bucket{type="http",le="10"} 举例,这个指标的值是 37092,表示小于等于 10s 的请求有 37092 次。直方图 Histogram 每个桶中统计的次数包含了前面的桶的次数。


histogram_quantile 在计算分位数时,就是判断指标样本中是否携带 le 标签,是的话才会纳入分位数的计算中。并且 histogram_quantile 函数是拿一组瞬时向量进行计算的,计算后得到一个分位数。


注意下概念,在 prometheus 中,向量 vector 是指 单个时间点的指标样本,矩阵 matrix 是一组时间点的样本。无论是 vector 还是 matrix,他们都可以是多个指标,不过区别在于指标的样本是单个时间点的,还是一组时间节点的。


拿上述指标举例,histogram_quantile 计算时就是拿指标名为 server_handle_seconds_bucket 的指标集合 某个时间节点的指标值进行计算的。指标集合包含下面几个指标


##  指标名和标签                                      指标值server_handle_seconds_bucket{type="http",le="0.005"} 0server_handle_seconds_bucket{type="http",le="0.01"} 0server_handle_seconds_bucket{type="http",le="0.025"} 0server_handle_seconds_bucket{type="http",le="0.05"} 0server_handle_seconds_bucket{type="http",le="0.1"} 0server_handle_seconds_bucket{type="http",le="0.25"} 0server_handle_seconds_bucket{type="http",le="0.5"} 0server_handle_seconds_bucket{type="http",le="1"} 0server_handle_seconds_bucket{type="http",le="2.5"} 0server_handle_seconds_bucket{type="http",le="5"} 0server_handle_seconds_bucket{type="http",le="10"} 37092server_handle_seconds_bucket{type="http",le="+Inf"} 37092
复制代码


所以我们在计算时为什么要将 server_handle_seconds_bucket{}[1m] 用 rate 函数进行计算,因为单独的 server_handle_seconds_bucket{}[1m] 返回的数据类型是 matrix 类型,是一组时间节点的样本,即某个 桶类型的指标有多个样本值,而 histogram_quantile 只要求一个桶类型的指标(携带 le 的指标)只有一个样本值。所以通过 rate 函数将一个矩阵类型的数据变成了向量类型

histogram_quantile 统计分位数原理

搞懂了为什么要用 rate 函数,再来看看为什么 rate 函数改变了桶的大小后不会对分位数计算逻辑产生影响。


拿文章开头的计算分位数的表达式举例


histogram_quantile(0.99,rate(server_handle_seconds_bucket{}[1m]))
复制代码


我们需要计算指标名为 server_handle_seconds_bucket 在过去 1 分钟内的数据的百分之 99 分位数。


histogram_quantile 计算步骤如下:


1, 首先会拿最后一个桶中(因为最后一个桶包含了所有样本的个数)的统计的次数去乘以分位数,看下第 99 分位是所有样本数据中的第几个,假设用 rank 变量存储这个结果。


2,拿上一步的计算结果 rank 值挨个桶比较统计次数,找到第一个桶的次数大于等于 rank 值的桶。这一步就计算出了 99 分位的样本是在哪个桶里。


3,最后通过下面的计算估算 99 分位数是多少


bucketStart + (bucketEnd-bucketStart)*(rank/count)
复制代码


bucketEnd 和 bucketStart 是桶的上下边界值,估算分位数是多少时,是默认在这个桶内,数据是线性均匀分布的,所以拿(bucketEnd-bucketStart)*(rank/count) 估算出 99 分为的数在这个桶内的偏移量。


所以,你可以看到分位数的计算虽然用到了 count 值,但是是拿 count 值和 rank 值相除得到一个比例,rate 函数虽然将桶指标的 count 值变小了,但由于计算时,我仅仅是求一个比例值,所以对分位数的结果运算并不影响。

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2020-09-17 加入

还未添加个人简介

评论

发布
暂无评论
prometheus Histogram 统计原理_Grafana_蓝胖子的编程梦_InfoQ写作社区