ChuChencheng / note

菜鸡零碎知识笔记
Creative Commons Zero v1.0 Universal
3 stars 0 forks source link

PromQL rate range 15s 无数据问题 #50

Open ChuChencheng opened 8 months ago

ChuChencheng commented 8 months ago

背景

本地搭的一套 Prometheus ,scrape_interval 设置为 15s 查询以下语句时,发现查不出数据

sum by (url) (rate(http_requests_total_c{url="/"}[15s]))

但是在另一套 Grafana 上查询时,使用 15s 是可以查到数据的

原因

本以为是 Grafana 的问题,于是本地也搭了一套 Grafana ,但是查询的结果是一样的

后来想到另一套系统使用的是 VictoriaMetrics

Grafana 社区中也查到了十分清楚的解释,感谢这位老哥

image

rate 在 Prometheus 中的限制

以上社区问答中,指明了在 Prometheus 中, rate range 至少需要是 scrape_interval 的两倍

而在另一篇文章中,说明通常 range 会是 scrape_interval 的四倍,以应对无数据、数据缺失等情况

PromQL 如何处理 rate

在以往的印象中, rate 就是取 range 区间内的前后两个数据点相减,再除以 range ,然而实际上不是这样的(一直没仔细看文档导致的错误印象)。

PromQL 计算 rate 确实会取头尾两个点,不过并不是直接取数据点,而是会先进行一个 推断(extrapolation) 的过程,例如:

我们要计算 00:05 这个时间点, range 为 5m 的数据,而实际的头尾数据点,并不一定准确落在 00:00 和 00:05 两个时间点上,假设头尾数据点是落在 00:01 和 00:04 两个时间点,这时候, PromQL 会把这两个点连线,得到一个二元一次方程,从而推断出 00:00 与 00:05 时间点的数据。注意,推断出的数据并不是真实的。

这篇文章中的图片所展示:

image

这个逻辑会有以下两个问题:

  1. 当 range 范围内只有一个数据点时无法计算 rate ,因为 PromQL 只取 range 范围内的数据点。这就是我遇到的 range 调为 15s 无数据的原因,也是网上建议 range 至少是 2倍 ,最好 4倍 scrape_interval 的原因。
  2. 由于 increaserate 一样有推断的逻辑,所以 increase 的结果可能会有小数,即使我们一般是对 Counter 类型(一般单调递增,数据点是整数)应用 increase 函数。

VictoriaMetrics MetricsQL 与 PromQL 对 rate 处理的区别

那么 VictoriaMetrics 使用的 MetricsQL 是如何解决上述两个问题的?

  1. 首先, MetricsQL 会把当前计算 range ($__interval) 的前一个 range 中,最后一个数据点考虑在内,当 range 范围内只有一个数据点时,会自动增加 range 的范围,解决 PromQL 中 range = scrape_interval 无数据的问题。
  2. 其次, MetricsQL 对 rateincrease 抛弃了推断逻辑,解决 increase 处理 Counter 出现的小数问题。

VictoriaMetrics 保留前一个 range 的数据点image

示例

本地 Docker 启动 Prometheus 与 VictoriaMetrics ,配置 Prometheus remote_write 写到 VictoriaMetrics 中,配合 Grafana 对比二者折线图差异

scrape_interval 为 15s

语句为

sum by (url) (rate(http_requests_total_c{url="/"}[$range]))

range 1m image

range 15s image

参考