背景
在 Prometheus 监控系统中,对于 counter 类型的容器常用的求导方式是 rate() 或 irate()。
在官网文档中,关于他们不同点的叙述如下:
rate
should only be used with counters. It is best suited for alerting, and for graphing of slow-moving counters.irate
should only be used when graphing volatile, fast-moving counters.
光看这两段文字比较抽象,接下来将通过一些详细的例子来讲述他们的原理与良好实践。
一个幽灵
同一个监控,同一个时间,只是因为 rate 的参数,展示出来的效果截然不同。
可以看到,rate[10m] 的图相对来说更加平滑,而 rate[1m] 则充满了波动。
最初我们以为是采样精度太低,按以往的经验 irate 是完全精确的,于是将函数改为了 irate,但是效果更加离谱。
而且通过其他监控项以及业务实际负载可以知道,真实的情况是类似于 rate[10] 那张图的。
到此时,我还心怀侥幸,认为是 rate 的平滑带来的问题,而随后的情况则更加诡异。
这是一张两天区间内的 rate[1m],注意到 11 月 1 日的部分、11 月 3 日的部分和上面七天区间的 rate[1m] 的对应部分是完全不同的。而和 rate[10m] 的部分则较为相似。
思索
我们知道,irate 取 counter 最近两个点的差值(在我们集群中,数据点的时间间隔默认是 15s),而 rate[1m] 取 1min 内的平均值。
因为 7day 时间区间拉的太大,导致他们算出来的值只有部分画在了图里(如果 12 小时内只能显示 50 个点,差不多 14 min 一个点),相当于做了一次采样,而采样出来的这些点在 11 日正好都落在了低谷,12日正常,13日落在了低谷。(疑点:按理来说随机采样应该不会发生这种情况,除非是业务的执行周期的波峰波谷正好对上了采样点,然后每次跨天时相位变一下)。
而 rate[10m] 会求 10min 内的平均值,相对来说能代表这个采样区间的平均值,所以更能代表实际情况,也更符合需求。
结论
所以官网文档里的“irate should only be used when graphing volatile, fast-moving counters. ”,我现在的理解是指查看的时间区间较短,比如一小时左右,这个时候画出的图能显示所有的数据点,此时 irate 显示的就是精确值,而 rate 显示的平滑后的值,不能满足需求。
而到了时间尺度极大(几天级甚至更高)的时候,irate 就类似于了随机值,而 rate 更能反应真实的趋势。
如何选择平均区间
平均区间,也就是 rate 函数的参数,而使用为 irate 则代表不进行平均。
很自然想到一个问题,promql 是在代码中就确定好了,如果平均区间太小,可能会在展示区间较大时出现随机抽样;而如果平均区间太大,又会在展示区间较小时过度平滑,无法查看精确值。
好在,grafana 想到了这个问题,可以将平均区间设置为系统变量 __interval
(适用于旧版 grafana)或 $__rate_interval
(适用于新版 grafana),此时 grafana 会按展示区间的尺度自动设定 promql 中的平滑区间,保证不同需求下的良好行为。
总结
- 【点在屏幕上的间隔】是提前确定好的,【屏幕尺寸】是固定的,所以【要展示的点数】也是固定的。
- 在选择了【展示区间】之后,【两个数据点间的时间间隔】就确定好了。
- 根据这些数据点的时刻,grafana 从 prometheus 中执行对应的 promql,获得数据。
举个例子:
- 我的电脑尺寸和 grafana 的设置,一屏共显示 2400 个点,这个是个常数。并且我正好打开了一屏。
- 我选择查过去十天的内容,那么每两个数据点之间的时间间隔是 102460/2400=6min.
- grafana 选好这些时间点,比如今天凌晨 0:00,0:06,0:12....
- grafana 按预设好的 promql 去找 prometheus 计算这些时间点的数据:
-
假设 promql 里面写着是 rate[1m],那么对于 0:00 的这个查询,prometheus 会返回 [23:59, 0:00] 内的真实数据的平均变化率。对于 0:06 这个查询,prometheus 会返回 [0:05, 0:06] 内的真实数据的平均变化率,依次类推。
注意到这个时候,[0:00, 0:05] 之间的数据不会对显示结果产生任何影响,这就是抽样所产生的随机性的来源。 -
假设 promql 里面写着是 rate[6m],那么对于 0:00 的这个查询,prometheus 会返回 [23:54, 0:00] 内的真实数据的平均变化率。对于 0:06 这个查询,prometheus 会返回 [0:00, 0:06] 内的真实数据的平均变化率,依次类推。这个时候所有的数据都会显示在最终的结果中。
-
假设 promql 里面写着是 rate[24m],那么对于 0:00 的这个查询,prometheus 会返回 [23:36, 0:00] 内的真实数据的平均变化率。对于 0:06 这个查询,prometheus 会返回 [23:42, 0:06] 内的真实数据的平均变化率,依次类推。这个时候所有的数据都会显示在最终的结果中,而且每个数据会被计算多次,相当于额外做了一些平滑。
-
参考
Why irate from prometheus doesn't capture spikes
# New in Grafana 7.2: $__rate_interval for Prometheus rate queries that just work
近期评论