prometheus使用数据外推与兼容跳变重置来优化处理窗口函数(rate,irate,increase)
场景
以下是用于计算计数器增长率的三个函数之间差异的高级概述:
- rate():这计算每秒的增长率,在整个提供的时间窗口内平均。示例:rate(http_requests_total[5m])生成 5 分钟时间窗口内平均的每秒 HTTP 请求速率。此函数是最常见的,因为它产生具有可预测的每秒输出单位的良好平滑速率。
- irate()(“即时速率”):这与 类似,计算每秒的增长率rate(),但仅考虑提供的时间窗口下的最后两个样本进行计算,并忽略所有较早的样本。示例:irate(http_requests_total[5m])查看提供的 5 分钟窗口下的最后两个样本,并计算它们之间的每秒增长率。如果您想让放大的图表显示对速率变化的快速响应,则此函数会很有帮助,但输出会比rate().
- increase():此函数与完全相同,只是rate()它不将最终单位转换为“每秒”( 1/s)。相反,最终的输出单位是每个提供的时间窗口。示例:increase(http_requests_total[5m])得出 5 分钟窗口内处理的 HTTP 请求的总增量(单位:)1 / 5m。因此increase(foo[5m]) / (5 * 60)100% 相当于rate(foo[5m]).
所有三个函数都要求在提供的范围窗口下至少需要两个样本才能工作。窗口下样本少于两个的系列将被简单地从结果中删除。
在给定固定时间窗口和属于该窗口的一些数据点的情况下,如何准确计算增量是一个权衡和不完美近似的问题。Prometheus 选择一种方法,旨在在仅给出所提供窗口下的有限数据的情况下提供平均最正确的答案。让我们更详细地看看它是如何做到这一点的:数据外推 + 处理计数器重置
数据外推
经常让人们感到困惑的是rate()和increase()函数的推断行为。例如,即使对于只有整数增量的计数器,也increase()可以返回非整数结果。2.5883原因是increase()试图近似计数器在指定时间窗口的总持续时间内的增加(例如,在 的情况下为 5 分钟increase(foo[5m]))。但实际上,在时间窗口下找到的第一个和最后一个样本永远不会与提供的时间窗口的开始和结束 100% 重合。因此increase()(也rate())将窗口下的第一个和最后一个数据点之间的斜率外推到窗口边界,以获得平均更接近整个窗口的预期增量的值(如果实际上在窗口边界精确存在样本) 。
下图显示了使用rate()1 分钟窗口和间隔 15 秒的样本的示例,1窗口下发生了一个实际计数器的增加:
正如您所看到的,报告的结果基于窗口下第一个和最后一个样本之间的斜率(几乎正确,请参阅下一节有关计数器重置的内容),并外推到窗口边界。
注意:这种推断行为有一些例外:当一个系列看起来像是在提供的时间窗口内开始或结束时,我们不想在该系列终止的方向上推断得太远。和函数猜测,当第一个或最后一个样本距其各自窗口边界的距离超过窗口下样本之间平均间隔的 1.1 倍时,序列将在窗口下开始或结束rate()。increase()在这种情况下,外推仅向窗口边界延伸平均样本间隔的一半,但不会一直延伸。同样,这些函数避免外推到负值,因为计数器始终从0并且永远不能为负数。0相反,外推仅在达到预期值之前发生。
由于irate()实际上只查看两个样本之间每秒的增量,因此它不会进行任何此类外推。
处理计数器重置
尽管计数器通常只会上升,但0只要跟踪它们的进程重新启动,它们就会重置。为了不将这些重置解释为实际的负利率,与计数器相关的函数具有检测和处理这些重置的逻辑:在提供的时间窗口下迭代样本时,这些函数检查是否有任何样本的值低于前一个样本的值,并将这种情况解释为计数器重置。0使用计数器始终在重置后开始的进一步假设,这些函数只需将新的样本值添加到之前看到的样本值中,以补偿重置。
以下示例图显示了rate()计算如何处理在提供的窗口下发生的计数器重置。您可以将其想象为rate()从底层“真实”样本创建一组“虚拟”样本。然后根据虚拟样本计算最终速率,就好像从未发生过重置一样:
注意:每当计数器重置时,它有可能在普罗米修斯最后一次刮擦之后、重置之前增加。这些增量对于普罗米修斯来说永远丢失了,而且没有办法找回来。为了最大限度地减少这种影响,重置应该偶尔发生一次,并且比普罗米修斯刮擦目标的频率要低得多。