您无法始终从 Prometheus 获得准确的费率/增量值,这是有实际原因的。其中之一是刮擦失败,即有时刮擦会由于服务缓慢、Prometheus 缓慢或网络问题而失败或超时。
另一个原因是收集的样本永远不会完全分开scrape_interval:总是会有几毫秒或几秒的延迟。那么(举一个极端的例子)如果你只有 2 个相隔 63 秒的样本,你怎么能知道过去 1 分钟的精确增加呢?这是两个值之间的差异吗?是调整到 60 秒的差异吗(即/ 63 * 60)?
话虽如此,Prometheus 仅查看严格在请求时间范围内的样本,从而进一步将自己限制在一个角落。解释一下:一个理性的人会如何计算计数器在过去 30 分钟内的增量?他们可能会取现在所述计数器的值和 30 分钟前的值并减去它们。 IE。用 PromQL 术语(必要时调整计数器重置):
request_duration_bucket - request_duration_bucket offset 30m
Prometheus 所做的(假设 scrape_interval 和 1m 以及一个理想的时间序列,其中样本之间的间隔恰好是 1m)基本上是这样的:
(request_duration_bucket - request_duration_bucket offset 29m) / 29 * 30
即增加超过 29 分钟并推断为 30。由于自我强加的限制,与手头问题的性质无关。
请注意,这适用于平稳且连续增加的计数器。例如。如果您有一个每分钟增加 500 的计数器,那么在 29 分钟内增加并推断为 30 是完全正确的。但是对于任何在跳跃和配合中增加的东西(这是大多数现实生活中的计数器),如果它发生在它实际采样的 29 分钟内(恰好是 1/29),它要么会略微高估增加,要么会严重低估它(如果增加发生在不包括在采样中的 1 分钟内)。如果您在覆盖较少样本的范围内计算速率/增量,情况会更糟。例如。如果您的范围平均仅涵盖 5 个样本,则高估将是 20%,即 1 / (5 - 1) 并且(每个)您的增加将在 5 分钟内完全消失 1 分钟。
我发现解决此限制的唯一方法是(再次假设 1m 中的 scrape_interval)对 Prometheus 的推断进行逆向工程:
increase(request_duration_bucket[31m]) / 31 * 30
但这需要您了解您的 scrape_interval 并进行调整,并且非常脆弱(如果您更改了您的 scrape_interval,那么您所有的仔细调整都会付诸东流)。
或者,如果您对每次重新启动实例时增量降至零感到满意:
clamp_min(request_duration_bucket - request_duration_bucket offset 30m, 0)
我确实有一个提议的 Prometheus 补丁来添加 xrate/xincrease 函数,这些函数实际上表现得更像你所期望的那样(如上所述),但它看起来不太可能被接受: https://github.com/prometheus/prometheus/issues/3806