写点什么

prometheus 描点原理

  • 2023-07-05
    广东
  • 本文字数:2235 字

    阅读完需:约 7 分钟

prometheus描点原理

大家好,我是蓝胖子,关于 prometheus 的入门教程有很多,拿我之前学 prometheus 的经历来讲,看了很多教程,还是会对 prometheus 的描点以及背后的统计原理感到迷惑,所以今天我们就来分析下这部分,来揭开其神秘的面纱。


我们先来看看 prometheus 里的数据模型是怎么样的,只有知道了数据结构,才能理解对后续这些数据如何描点,如何计算出相应指标值。

数据模型

prometheus 中存的是时序数据,时序数据有个特点是每条数据都有一个时间戳,并且时序数据都有一个 metric_name(指标名),和一系列的 label,以及当前指标的值 value。当用 prometheus web 控制台查询出来的就是一条条时序数据,如下图所示:



时序数据描述一个指标的表达式可以归纳为:


metric_name{label_name1=label_val1,label_name2=label_val2,....}  
复制代码


表达式开头是指标名,{}里的就是指标的标签。


在 prometheus 中,如果指标名和标签完全相同,那么将会认为他们是同一个指标,将一个指标不同时间戳的时序数据称为指标的样本。


这里要特别明确一点,用过 prometheus 客户端的同学都知道 prometheus 有四大指标类型 Counter,Guage,Histogram,Summary,但无论是哪种指标类型在 prometheus 服务端这边都是按照上述的指标格式进行存储的,prometheus server 在存储时并不会去存特定某个指标是什么指标类型。


理解了 prometheus server 存储数据的类型,我们再来看看对 prometheus server 进行查询时的数据返回类型。


prometheus server 提供了两个 api 对外提供查询,分别是 queryquery_range ,在 prometheus 中 用 vector 类型表示单个时间点的指标数据,用 matrix 表示一组时间点的指标数据。所以 query_range api 只能返回 matrix 类型的数据。我们用 prometheus web 控制台演示下。


首先来看下在 table 列进行查询时涉及的查询,在 table 列进行查询会调用到 query 的 api,其返回结果既可以是 matrix 类型,也可以是 vector 类型。



如上图所示,查询返回的是 vector 类型的数据 , 我们在 table 这一栏输入 PromQl 查询语句,默认是查出当前时间最新的指标,可以看到返回的 result 是一个数组,因为匹配查询语句的不止一个指标,接着返回了指标的时间戳以及对应的值 val。


在 table 这一列除了查询某个指标的瞬时值,还可以查某段时间内的值,对应的 prometheus server api 的返回类型就将是 matrix 类型了 ,如下图所示,我们可以修改 PromQl 语句让其查 1m 内的数据:



如上图所示,将查询语句改为 go_memstats_other_sys_bytes{}[1m] 后返回的就是 matrix 类型的数据了,它表示一组时间点的数据。


其实看到这里,你应该能想到,prometheus 绘图就是根据 matrix 类型的数据进行描点绘图的

描点原理

紧接着,我们就来看下 prometheus 的描点绘图原理。


首先要明确一点,绘图的原理本质上就是在一个个时间片段里进行描点,然后再将各个点连起来就形成了随时间变化的监控图 Graph。所以在描点绘图时,用到的数据查询结果仅仅只能是 matrix 类型,因为只有它才能表示一个指标一组时间点的样本值。


我们再回顾下 matrix 数据格式是怎样的,



matrix 数据格式的返回,每个指标都会携带一组时间点的样本,到时候描点时就是根据这些样本点的时间点为横坐标,样本的值为纵坐标进行绘图的。


接着,我们来看下绘图用到的查询数据 api, 和在 table 栏进行查询不同,在绘图界面查询数据用到的 api 是 query_range ,query_range 返回的数据格式是 matrix 类型的数据



注意下 query_range 的参数,已经和 query 不同了,因为 query 毕竟只查基于某个时间点的数据,而 query_range 是查某段时间的数据,所以 query_range 有个开始时间 start 和结束时间 end,除此以外,它还有个参数 step,这个参数是表示将 start 和 end 之间的时间段按 step 步长分割为更小的时间段,然后在每个小的时间段内将会产生一个描点 。最后就是将指标的描点全部连接起来就是一个曲线了。

描点是如何计算出来的

知道了在每个小的时间段内,prometheus 会产生一个描点,我们还需要知道描点究竟是如何计算出来的。


拿截图的表达式 rate(go_memstats_other_sys_bytes[1m]) 举例,假设时间区间[start,end]被 step 分成了 3 小段。



如上图,其中每段的开始时间戳分别是 A1,A2,A3,按 step 进行累加,这 3 个小的时间段将会产生 3 个描点,每个描点计算规则如下:


val=rate函数(当前时间段与当前时间段减去1m这段时间内的所有样本)
复制代码


每个描点,都会执行一次 rate 函数得到描点的 value 值,描点的时间戳则是每个小的时间段开始的时间,而计算的样本则是 每个小的时间段开始时间到 之前的 1m 的时间范围内筛选出来的。

histogram_quantile 表达式如何描点的?

上面的描点例子比较简单,我们来看一个复杂点的,这个也是 Histogram 指标类型统计的原理。


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


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


它描点的逻辑依然逃不开 将一个大的时间段分为小的时间段,并且每个小的时间段产生描点。也就是说,每个小的时间段也都会执行一次 histogram_quantile 函数得到描点值,但 histogram_quantile 的样本值从哪里得来呢?


是在小的时间段内通过 rate 函数计算得到的,rate 函数的样本来源也和刚才讲的一样,是当前时间段与当前时间段减去 1m 这段时间内的所有样本。

思考题

这样的确得到了 3 个描点,能绘制出曲线来,但最开始我在看到这个表达式还是很疑惑的,因为它将之前的每个直方图的指标都进行了 rate 计算,这样在用 histogram_quantile 计算最终分位数的时候不会导致结果变化吗?这就涉及到了 histogram_quantile 计算分为数的逻辑,有空我会在下篇文章继续分析。

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

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

还未添加个人简介

评论

发布
暂无评论
prometheus描点原理_Docker_蓝胖子的编程梦_InfoQ写作社区