17.5.2 向量类型与选择器:瞬时/区间/子查询

PromQL 的结果类型以向量为核心,分为瞬时向量(Instant Vector)与区间向量(Range Vector),并基于选择器(Selector)与子查询构造不同时间维度的数据集。理解它们的评估时刻、采样边界与返回结构,是正确聚合与告警的基础。

文章图片

1. 向量类型与选择器核心概念#

瞬时向量(Instant Vector)
在某一评估时刻返回一组时间序列及其“最新样本”。典型选择器:
- up{job="node"}
- node_memory_MemAvailable_bytes{instance="10.0.0.1:9100"}

区间向量(Range Vector)
在评估时刻之前的时间窗口内返回样本序列。选择器写法:
- node_cpu_seconds_total{mode!="idle"}[5m]

子查询(Subquery)
对一个表达式产生的瞬时向量再做时间范围采样:
- rate(http_requests_total[5m])[30m:1m]

2. 示例:瞬时/区间/子查询对比#

# 瞬时向量:当前是否存活
up{job="node"}

# 区间向量:过去5分钟CPU非空闲样本序列
node_cpu_seconds_total{mode!="idle"}[5m]

# 区间向量 -> 瞬时向量:5分钟平均CPU使用率
avg by (instance) (
  rate(node_cpu_seconds_total{mode!="idle"}[5m])
)

# 子查询:先算5分钟速率,再对30分钟内每分钟采样
rate(http_requests_total[5m])[30m:1m]

命令解释:
- [5m] 是区间窗口,需覆盖至少 2~4 个抓取周期
- [30m:1m]30m 是回溯范围,1m 是评估步长
- rate() 接受区间向量,输出瞬时向量

3. 标签选择器模式与命令说明#

# 精确匹配:性能最好
node_filesystem_avail_bytes{fstype="ext4",mountpoint="/"}

# 正则匹配:成本高,谨慎使用
http_requests_total{job=~"api|web",env!="test"}

# 否定匹配:剔除某类标签
up{job!="blackbox"}

命令解释:
- = 等值匹配
- =~ 正则匹配
- != / !~ 否定匹配
- 正则会增大 CPU 和内存成本

4. 查询验证与命令行工具(含安装)#

使用 promtool 验证 PromQL 语法与表达式:

安装与验证:

# 下载 promtool(以 Linux amd64 为例)
wget https://github.com/prometheus/prometheus/releases/download/v2.49.0/prometheus-2.49.0.linux-amd64.tar.gz
tar -xf prometheus-2.49.0.linux-amd64.tar.gz
cd prometheus-2.49.0.linux-amd64

# 验证表达式
./promtool query instant http://127.0.0.1:9090 'up{job="node"}'

预期效果:
- 返回向量结果或空集
- 若语法错误,promtool 会提示行列位置

5. 排错清单(常见“无数据”与 NaN)#

  1. 抓取间隔与窗口不匹配
    - 抓取间隔 30s,但使用 [1m] 可能仅 2 个点
    - 建议窗口 >= 2 * scrape_interval

  2. 指标名称或标签错误
    - 用 label_values 在 Grafana/Prometheus UI 中验证

  3. 子查询步长过小导致超时
    - 将 [30m:1s] 调整为 [30m:1m]

  4. 区间向量直接算术计算
    - 先用 rate()_over_time 转换为瞬时向量

6. 练习(含预期目标)#

  1. 练习 1:判断节点是否离线
    - 目标:返回 up{job="node"} == 0 的实例
    - 答案示例:
    promql up{job="node"} == 0

  2. 练习 2:计算过去 10 分钟平均 CPU 使用率
    - 目标:按实例输出平均 CPU 使用率
    promql avg by (instance) ( rate(node_cpu_seconds_total{mode!="idle"}[5m]) )

  3. 练习 3:对 HTTP QPS 做 1 小时趋势平滑
    - 目标:先算 QPS,再做 1 小时区间平均
    promql avg_over_time(rate(http_requests_total[5m])[1h:1m])

7. 实战建议#

  • 告警优先使用瞬时向量与平滑函数(avg_over_time),避免抖动
  • 趋势分析使用区间向量并控制窗口长度
  • 子查询适合多级平滑,但避免在高基数指标上频繁使用
  • 稀疏采样指标优先使用 _over_time 族函数而非 rate()