本期作者:沈亚军
爱可生上海研发中心成员,研发工程师。


Prometheus 数据基本查询

上篇文章【第04期:Prometheus 数据采集(三)】介绍了 Prometheus 数据采集流程,本文开始将介绍 Prometheus 数据查询。本文会介绍数据查询的基本使用。

PromQL 简介

Prometheus 通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而 label 则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。Prometheus 提供了一种称为 PromQL 的功能查询语言,使用户可以实时选择和汇总时间序列数据。表达式的结果可以显示为图形,可以在 Prometheus 的表达式浏览器中显示为表格数据,也可以由外部系统通过 HTTP API 使用。在 Prometheus 的表达语言中,一个表达式或子表达式可以计算为以下四种类型之一:

  • 瞬时向量(Instant vector):一组时间序列,每个时间序列包含一个样本,所有样本共享相同的时间戳。
  • 范围向量(Range vector):一组时间序列,其中包含每个时间序列随时间变化的一系列数据点。
  • 标量(Scalar):一个简单的数字浮点值。
  • 字符串(String):一个简单的字符串值,目前未使用。

PromQL 基本使用

时间序列选择器

瞬时向量选择器

瞬时向量选择器允许在给定的时间戳上选择一组时间序列和每个样本的单个采样值,返回值中只会包含该时间序列中的最新的一个样本值。

当我们直接使用监控指标名称查询时,可以查询包含该 metric 名称的所有时间序列。以下两种表达方式是等同的:

http_requests_total

该表达式会返回指标名称为 http_requests_total 的所有时间序列。

http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}=(20889@1518096812.326)

通过在花括号 {} 中添加逗号分隔的标签匹配器列表,可以进一步过滤这些时间序列。

如果我们只需要查询所有 http_requests_total 时间序列中满足标签 job 为 prometheus 且 group 为 canary 的时间序列,可以使用如下表达式。

http_requests_total{job="prometheus",group="canary"}

PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。

  • 通过使用 label=value 可以选择那些标签满足表达式定义的时间序列

  • 反之使用 label!=value 则可以根据标签匹配排除时间序列

  • 使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列

  • 反之使用 label!~regx 进行排除

例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:

http_requests_total{environment=~"staging|testing|development",method!="GET"}

在标签匹配中如果指定标签值为空,会匹配所有不包含该标签的时间序列,同一标签名称可有多个匹配器。

向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器。

以下表达式是非法的,

{job=~".*"}

相反,这些表达式是有效的,因为它们都有一个与空标签值不匹配的选择器。

{job=~".+"}

标签匹配还以使用内部的 ** name** 标签应用到 metric 名称,如 http_requests_total 等同于**{name=“http_requests_total”}**,
下面的表达式会筛选出所有以 **job:**开头的 metric,

{__name__=~"job:.*"}

另外 metric 名称不能包含以下关键字:boolonignoringgroup_leftgroup_right 可使用如下方式代替,

{__name__="on"}

Prometheus 中的所有正则表达式都使用 RE2 syntax.

RE2 syntax:
https://github.com/google/re2/wiki/Syntax

区间向量选择器

范围向量文字的工作方式与即时向量文字相同,不同之处在于,它们从当前瞬间选择了一定范围的样本。语法上,将范围持续时间附加在向量选择器末尾的方括号([])中,以指定应为每个结果范围向量元素提取多远的时间值。

区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。

时间范围选择器内容指定为数字,紧随其后的是以下单位之一:

  • s - seconds
  • m - minutes
  • h - hours
  • d - days
  • w - weeks
  • y - years

例如,如通过以下表达式可以选择最近 5 分钟内的所有样本数据:

http_requests_total{job="prometheus"}[5m]

时间偏移

在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准。

http_request_total{} # 瞬时向量表达式,选择当前最新的数据

而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢?这个时候我们就可以使用位移操作,可以使用 offset 时间位移操作:

http_request_total{} offset 5m

需要注意的是 offset 关键词需要紧跟在选择器之后。

sum(http_requests_total{method="GET"} offset 5m) // 正确

存储设计原理简介

时序数据的存储分俩个维度,如下图所示,纵轴表示所有存储的序列数据,横轴表示数据的时间分布:

promutheus 会定期拉取数据,从横轴的右侧垂直写入数据, 而我们在执行查询的时候,往往是查询图中任意矩形区域的数据,时序数据的存储和读取模式有着很大的差异,为了同时满足写入和查询两种不同需求,对存储层的时间有比较高的要求,如果在 k8s 环境,由于 pod 不断的新建和重启,时序数据会变成如下图的线性分布,更是提高了存储和查询难度。

样本数据压缩

Prometheus 每秒会采集大量的数据,数据压缩势在必行,Prometheus 基于同一个序列的数据相似度比较高,在内存可以把每个数据点压缩到平均 1.37 byte 大小。

时间分片

Prometheus 的存储层把数据划分成了不同的块,如下图所示:

每个块保存了在该时间段内的序列数据,每个数据块可以单独行使数据库行为,优点如下:

  • 在指定一个时间范围时只需要查询其中一些子块,能有效的减少查询时间。

  • 解决了由于服务不断的新建和重启,时间序列数据呈线性分布的问题。

  • 更方便的根据时间删除过期数据。

倒排索引

通常情况下用户会根据标签检索数据,但是由于标签是用户自定义不同的应用会有不同的标签,因此不能像传统数据库一样在标签上建立索引,为了提高查询效率,因此 Prometheus 把每个时序的描述当作一个小文档,建立了倒排索引,如:requests_total{path="/status",method=“GET”, instance=“10.0.0.1:80”} 的文档包含如下关键词:name=“requests_total”path="/status"method=“GET”instance="10.0.0.1:80,对于每个时序数据唯一的 label 会为其建立额外的索引行,每个索引行对应一个有序的 ID 列表,每个 ID 对应一条时序数据,这些列表可高效的合并或相交,以满足复杂的查询场景。

常用函数和操作符介绍

rate

rate 是专门搭配 counter 类型数据使用的函数,计算范围向量中时间序列的每秒平均增长率,当counter 出现单调性中断会自动进行调整,计算时会根据有效值在时间范围内的比例扩大时间区间范围,从而允许数据丢失或时间范围与数据拉取的时间段不完全对齐。

如:计算 job 为 api-server 的请求在 5m 内增长率。

rate(http_requests_total{job="api-server"}[5m])

irate

irate 适用于变化频率高的 counter 类型数据,计算范围向量中时间序列的每秒平均增长率。基于最后两个数据点。当 counter 出现单调性中断会自动进行调整,与 rate 不同的是,irate 只会选取时间范围内最近的两个点计算,当选定的时间范围内仅包含两个数据点时,不考虑外推情况,rateirate 并无明显区别。

如:计算 job 为 api-server 的请求在 5m 内增长率。

irate(http_requests_total{job="api-server"}[5m])

predict_linear

predict_linear 可用于 gauges 类型数据,predict_linear 函数可以预测时间序列 v 在 t 秒后的值,它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。例如,基于 2 小时的样本数据,来预测主机可用磁盘空间的是否在 4 个小时候被占满,可以使用如下表达式:

predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0

当资源占用不是平滑变化的使用 predict_linear 可以做到提前预警,可以有效避免基于资源用量是平滑增长的的阈值告警模式出现的告警还未来的及处理系统就不可用的情况。

聚合操作符

PrmoQL 提供了内置的聚合操作符,包括 summinmaxavggroupcoun****t etc,表达方** [without|by ()] ([parameter,] )** 或 ([parameter,] ) [without|by ()]without 会从结果向量中删除列出的标签,而所有其他标签将保留输出。by 会执行相反的操作并删除 by 子句中未列出的标签,paramer 仅在使用 count_valuesquantiletopkbottomk,需要指定,举例如下:

sum without (instance) (http_requests_total) // HTTP requests per application and group

使用建议

聚合操作符的使用顺序

  • 先使用 sum 再使用 rate,原因是在服务器重启的情况下 counter 会被置 0,如果先使用 sum 再使用 rate,重启现象会被掩盖,从而会出现假峰值,其它类似的操作符和函数还有 minmaxavgceilhistogram_quantilepredict_linear etc。

  • 可直接安全的作用与 counter 的操作符有 rateirateincreaseresets 其它都需要慎重考虑引起的其它问题。

避免慢查询和数据过载

  • 当数据量很大时,对其直接进行查询或绘图时很有可能导致服务器或浏览器过载或超时,合理的做法是指定合理的时间范围和查询步长,可以在 Prometheus 自带的查询界面构建查询表达式增加标签进行筛选或聚合,直到获得一个合理的查询结果集。

  • 当使用以上方式仍不能完全缓解查询压力,可以通过 Recording Rules 保存常用的查询数据以提高查询效率。

**Recording Rules:**https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules

时间范围和数据拉取间隔

时间范围通常大于等于 4 倍数据拉取时间间隔,举例:当数据拉取间隔为 10s, rateirate 至少需要两个样本点,所以需要 30s 来保证至少覆盖两个时间点,考虑到某个时间点拉取出错,所以 40s 是一个较为合理的时间范围,实际使用通常取整到 1m 举例:irate(http_requests_total{job=“api-server”}[1m])

  • 对于 irate 指定一个大的时间范围没有意义的,通常指定为四倍数据拉取时间间隔

  • 对于 rate 没有明确的建议,需要考虑的是时间范围越大,会拉平出现的数据峰值,获得更为平缓的速率

irate 和 rate 和查询步长

  • 当调用 /api/v1/query_range 获取绘图数据时,需要指定参数 query 查询范围,指定获取时间序列样本量的大小,step 查询步长,查询步长决定了绘图点的个数,步长越小绘图点越多,考虑到图的直观及可读性需要选择合适的步长。

  • irate 适合快速变化的计数器, 当查询步长大于 irate 时间范围时,由于其只取最后两个数据点,可能会导致在时间范围外的数据峰值点未能被捕获,查询步长与其时间范围越接近, 会捕获更多的数据峰值,曲线变化也更灵敏精确,推荐在重要且需要监测其细节变化的 metric 中使用。

  • 大多数情况下我们可以使用 rate,但需要注意的是时间范围不应当小于步长,否则可能会漏掉数据。


相关内容方面的知识,大家还有什么疑问或者想知道的吗?赶紧留言告诉小编吧!

第05期:Prometheus 数据查询(一)相关推荐

  1. Prometheus:Java调用PromQL工具类(瞬时数据查询)

    目录 PostMan瞬时数据查询:Windows主机空闲内存量 请求 响应数据 Java:调用PromQL工具类(瞬时数据查询) Prometheus返回结果反序列化 Prometheus常用Prom ...

  2. Java网页数据采集器[下篇-数据查询]【转载】

    本期概述 上一期我们学习了如何将html采集到的数据存储到MySql数据库中,这期我们来学习下如何在存储的数据中查询我们实际想看到的数据. 数据采集页面 2011-2012赛季英超球队战绩 如果是初学 ...

  3. Hive的JDBC连接和数据查询功能

    实验材料及说明 在Ubuntu系统的/学号(每个人之间的学号)/salesInfo目录下,有买家的购买记录文件Sales,该文件记录了买家的id,购买商品的id以及购买日期,文件为名为Sales.Sa ...

  4. Zabbix 4.2 发布:支持Prometheus数据收集,可扩展性大大提升

    4月2日,Zabbix正式发布了Zabbix 4.2版本.Zabbix具备现代监控系统所应提供的一切功能,包括数据收集与处理.分布式监控.实时问题与异常检测.警报.升级.乃至可视化等等. 下面是Zab ...

  5. JavaWeb黑马旅游网-学习笔记05【分类数据展示功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  6. prometheus连续查询_Grafana + Prometheus快速搭建监控平台

    随着业务的越发复杂,软件系统也越来越庞大,对软件系统的要求越来越高,意味着我们需要随时掌控系统的运行情况.因此,系统的实时监控以及可视化展示,就显得非常重要. 今天来介绍下使用Grafana + Pr ...

  7. Grafana教程(prometheus 基本查询语法,alerting报警)

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 prometheus原理可以参考:https://blog.csdn.net/luanpeng825485697/article/details/82 ...

  8. 数据查询和业务流分开_一文带你了解大数据管道

    介绍 如果您从大数据开始,通常会被众多工具,框架和选项所困扰. 在本文中,我将尝试总结其成分和基本配方,以帮助您开始大数据之旅. 我的目标是对不同的工具进行分类,并试图解释每个工具的目的以及它如何适应 ...

  9. 【MySQL练习】数据查询(02)-简易版

    ---------------------MYSQL练习题:数据查询(02)-简易版---------------------- 提供了数据查询进阶版练习题的各种目录文件,便于对照自己思索练习: 增强 ...

最新文章

  1. 田志刚:企业知识库如何跟Google、百度竞争?
  2. 数据类型,运算符和表达式03 - 零基础入门学习C语言04
  3. python语言入门p-python入门基础教程04 Python程序基本组成
  4. Hibernate与 MyBatis的比较
  5. Python和OpenCV环境配置
  6. Software develop Model
  7. Windows 11 dapr 环境安装
  8. Python之异常追踪模块:traceback
  9. python怎样实现多表连接_Python Day45多表连接查询
  10. Python数据挖掘-相关性-相关分析
  11. java如何把方法封装成接口,RxJava配合Retrofit实现网络封装
  12. 国内PC版64位谷歌浏览器离线下载安装地址
  13. 如何使用dd工具进行磁盘读写性能测试
  14. 10款微信公众平台相关的开源软件
  15. 沧海的孤塔-chimera
  16. EDM邮件营销需要开展多久才能取得最佳的营销效果
  17. linux wifi开机自动连接 wifi连接
  18. ios和android下数字没有垂直居中,手机端设置小号字体的上下居中问题
  19. 青少年CTF-WEB-Queen
  20. 【MySQL基础攻难1】聚集函数和分组查询

热门文章

  1. asp recordset 教程
  2. Minicom使用方法
  3. 中英文说明书丨艾美捷CD8α体内抗体介绍
  4. 推荐一个动漫风格转换的开源项目!可在线运行
  5. 关于Thread.IsBackground属性的理解
  6. html css is图片,isbackground
  7. 加密锁ROCKEY-ARM外壳加密演示
  8. vector容器 常用函数
  9. ListView控件的使用方法,以及数据的绑定(关于会员等级)
  10. Substitution 的用法