理解Prometheus的rate()函数
索引
-
- 首先
-
- 机制
-
- 2.1 参数类型
-
- 2.2 选择范围矢量的时间范围
-
- 2.3 计算
-
- 2.4 外推:在信息缺失时rate()函数的行为
-
- 2.5 聚合
-
- 例子
-
- 3.1 告警规则
- 3.2 计算SLO
首先
Prometheus和其查询语言PromQL拥有许多函数,用于对保存的数据进行各种计算。其中最常用的函数之一是rate()函数,但也是最容易被误解的函数之一。
如果公司内部有像Metricfire提供的监控工具,就可以提供所需的基本功能。其中一个重要功能是预测趋势。这就是rate()函数的用途。正如其名称所示,它可以计算在某个时间范围内的值增长率的每秒平均值。该函数可用于计算例如随着时间的推移服务器收到的请求数量或服务器的CPU使用率。首先要理解其内部机制,然后积累知识。如果您想尝试自己使用Prometheus,请立即注册MetricFire的Hosted Prometheus的免费试用版。
2. 机构形式
2.1 参数类型 de
在PromQL中,有两种参数类型:Range Vector和Instant Vector。通过图表可以看出,这两种类型分别如下所示。
这是一个由3个Range Vector矩阵组成的数据集,每个矩阵包含每10秒进行一次的1分钟数据获取。因此,这是一个由标签对唯一确定的数据集。Range Vector具有时间维度(在这种情况下为1分钟),而Instant Vector则没有。Instant Vector的定义如下。
这是Instant Vector的定义方式,它仅指定最后获取/抓取的值,并且rate()函数及其关联方法接受范围类型的参数。这是因为为了计算任何类型的变化,至少需要两个时间点的数据。因此,如果样本数少于2,则不会返回任何结果。PromQL通过在选择器旁边用方括号括起来的时间范围来表示Range Vector。它表示要与过去多长时间的数据进行比较。
2.2 选择时间范围的范围矢量
关于这个问题,应该选择哪个时间范围呢?并没有一个模范答案。作为最低要求,需要将获取间隔加倍。然而,在这种情况下,结果将变得非常”锐利”,值的变化将比其他任何时间范围的函数结果都快。然后,结果会立即返回0。如果将时间范围延长,可以获得相反的结果。结果的线条(如果将结果绘制出来)会变得”平滑”,很难找到尖峰值。因此,在Grafana中,建议将时间范围作为变量(例如:1m、5m、15m、2h)进行管理。这样,在尝试检测尖峰或趋势等情况时,可以选择最适合情况的值。
另外,在Grafana中,还可以使用特殊变量$__interval,该变量定义为将时间范围除以步长的大小得到的值。看起来,考虑了每个步长间的所有数据点,似乎是一个完美的解决方案,但前面提到的问题仍然存在。无法同时查看非常详细的图表和广泛的趋势。此外,时间间隔与查询步长相关联,因此当获取间隔更改时,可能会在非常短的时间范围内出现问题。
2.3 运算
在中国,只需要一个选项将其改写成中文:
和其他函数一样,rate() 函数也会在每个步骤中被评估。然而,它是通过什么机制来运作的呢?总体而言,它的计算方式大致如下。
rate() 函数的优点是它考虑了所有数据点,而不仅仅是首尾的数据点。另外也存在一个只使用首尾数据点的 irate() 函数。现在你可能会想为什么不使用 delta() 函数。现在已经解释了 rate() 函数具有根据复位自动调整的优秀特性。这可以理解为它只适用于“计数器(Counter)”这种指标类型,即那些持续增加的指标。它不适用于“仪表(Gauge)”这种指标类型。而且,如果你是一个热心的读者,你可能已经注意到使用 rate() 函数是为了避免浮点数在指标值中的使用限制,当达到限制时,浮点数将无限增长,因此进行“翻转”。通过这种逻辑,可以防止旧数据丢失,因此如果需要该功能,则建议使用 rate() 函数。
注意:由于这种复位的自动调整,如果与 rate() 函数一起使用其他聚合函数,则必须先应用 rate() 函数。否则,计数器的复位将不会被捕捉到,导致意想不到的结果。
不管怎样,目前 PromQL 不能阻止在“仪表(Gauge)”中使用 rate() 函数。因此,在选择要将哪个指标传递给该函数时,了解这一点非常重要。在“仪表(Gauge)”中使用 rate() 函数是不正确的。这是因为复位检测逻辑会错误地捕捉到因“计数器复位”而下降的值,从而得到错误的结果。
总之,假设有以下变化的计数器指标。
-
- 0
-
- 4
-
- 6
-
- 10
- 2
在“10”和“2”之间的重置被irate()函数和rate()函数捕获,然后的值被解释为是“12”,也就是比“2”(从0开始)增加了2个单位。假设在60秒内使用rate()函数计算速率,并在理想的时间戳下获取了这6个样本,那么每秒的平均增加率将如下所示:
12-0/60 = 0.2。因为在这种情况下一切都是完全理想的,所以逆计算(0.2*60=12)也是正确的。然而,如果某些样本并没有完全覆盖整个范围,或者在样本获取期间发生了随机延迟,导致它们无法完全对齐,那么这种逆计算并不总是成立。关于这一点,将在下一部分进行详细说明。
2.4 外推:当信息缺失时,rate()函数的行为
最後に,理解 rate() 函数执行外推的重要性是关键的。如果你知道这一点,你就不用长期困扰了。当 rate() 函数被执行时,一些获取 (scrape) 可能会失败,一些数据可能会丢失。此外,由于随机性的加入,即使是时间范围向量的倍数,它也不会完全匹配范围向量。
在这种情况下,rate() 函数会从保持的数据中计算出比率,并使用第一个或最后两个数据点来估计所选窗口的开始或结束,若存在信息缺失。这意味着即使所有数据点都是整数,结果也可能不均匀。因此,此函数只适用于检测趋势、尖峰和发生警告的情况。
2.5 统计
与其他函数类似,您也可以只将rate()函数应用于特定的维度。例如,rate(foo) by (bar) 将计算在所有bar(标签名称)下,foo的变化率。这在使用haproxy并想要计算不同后端的错误数变化率时非常有用。您可以按照以下方式编写:
rate(haproxy_connection_errors_total[5m]) by (backend)
例:
3. 例子
Note: “例” in Chinese can be translated to “example” or “case”, but it is commonly used in combination with other words to form phrases or idioms.
3.1 警报规则
正如前面所述,rate()函数在错误数量急剧增加时完美地接收警报。因此,可以创建如下警报:
通过这个,如果任何一个后端出现连接错误将会收到通知。因此,rate() 函数非常适合这种用途。请随时使用 Metricfire 来监控服务并尝试实施类似的警报。
3.2 计算SLO
在使用中文进行重述时,请注意以下事项:
1. rate() 函数的另一个常见用例是计算 SLI 并检查是否违反了 SLO / SLA。最近,Google 发布了一本受 SRE 欢迎的书籍。计算服务可用性的方法如下:
Please note that the translation may vary depending on the specific context and intended meaning.
以这种方式,我们可以计算出除去5xx响应之外的所有请求量的变化率,并将其除以请求总量的变化率。如果存在5xx响应,结果值将小于1。重复一遍,您可以在警报规则中指定某个阈值来使用此公式,以便在超过阈值时接收到警报,或者使用predict_linear函数来预测近期的情况,从而避免SLA/SLO问题。
请参考MetricFire的托管Prometheus页面获取更详细信息。同时,如果您希望尝试,可以注册免费试用版的托管Prometheus。您也可以预约演示,了解有关Prometheus最佳监控解决方案的信息。