prometheus 描点原理
大家好,我是蓝胖子,关于 prometheus 的入门教程有很多,拿我之前学 prometheus 的经历来讲,看了很多教程,还是会对 prometheus 的描点以及背后的统计原理感到迷惑,所以今天我们就来分析下这部分,来揭开其神秘的面纱。
我们先来看看 prometheus 里的数据模型是怎么样的,只有知道了数据结构,才能理解对后续这些数据如何描点,如何计算出相应指标值。
数据模型
prometheus 中存的是时序数据,时序数据有个特点是每条数据都有一个时间戳,并且时序数据都有一个 metric_name(指标名),和一系列的 label,以及当前指标的值 value。当用 prometheus web 控制台查询出来的就是一条条时序数据,如下图所示:
时序数据描述一个指标的表达式可以归纳为:
表达式开头是指标名,{}里的就是指标的标签。
在 prometheus 中,如果指标名和标签完全相同,那么将会认为他们是同一个指标,将一个指标不同时间戳的时序数据称为指标的样本。
这里要特别明确一点,用过 prometheus 客户端的同学都知道 prometheus 有四大指标类型 Counter,Guage,Histogram,Summary,但无论是哪种指标类型在 prometheus 服务端这边都是按照上述的指标格式进行存储的,prometheus server 在存储时并不会去存特定某个指标是什么指标类型。
理解了 prometheus server 存储数据的类型,我们再来看看对 prometheus server 进行查询时的数据返回类型。
prometheus server 提供了两个 api 对外提供查询,分别是 query 和 query_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 个描点,每个描点计算规则如下:
每个描点,都会执行一次 rate 函数得到描点的 value 值,描点的时间戳则是每个小的时间段开始的时间,而计算的样本则是 每个小的时间段开始时间到 之前的 1m 的时间范围内筛选出来的。
histogram_quantile 表达式如何描点的?
上面的描点例子比较简单,我们来看一个复杂点的,这个也是 Histogram 指标类型统计的原理。
如下,我们通常会用到 histogram_quantile 去计算服务接口时间的耗时情况。
它描点的逻辑依然逃不开 将一个大的时间段分为小的时间段,并且每个小的时间段产生描点。也就是说,每个小的时间段也都会执行一次 histogram_quantile 函数得到描点值,但 histogram_quantile 的样本值从哪里得来呢?
是在小的时间段内通过 rate 函数计算得到的,rate 函数的样本来源也和刚才讲的一样,是当前时间段与当前时间段减去 1m 这段时间内的所有样本。
思考题
这样的确得到了 3 个描点,能绘制出曲线来,但最开始我在看到这个表达式还是很疑惑的,因为它将之前的每个直方图的指标都进行了 rate 计算,这样在用 histogram_quantile 计算最终分位数的时候不会导致结果变化吗?这就涉及到了 histogram_quantile 计算分为数的逻辑,有空我会在下篇文章继续分析。
版权声明: 本文为 InfoQ 作者【蓝胖子的编程梦】的原创文章。
原文链接:【http://xie.infoq.cn/article/d5636d0c480de627d803dce64】。文章转载请联系作者。
评论