Prometheus监控指标查询性能调优

news2025/4/22 10:20:32

01

   背景

在《SRE: Google运维解密》一书中作者指出,监控系统需要能够有效的支持白盒监控和黑盒监控。黑盒监控只在某个问题目前正在发生,并且造成了某个现象时才会发出紧急警报。“白盒监控则大量依赖对系统内部信息的检测,如系统日志、抓取提供指标信息的 HTTP 节点等。白盒监控系统因此可以检测到即将发生的问题及那些重试所掩盖的问题等”。为了完善系统的白盒监控,会员团队基于 Prometheus + Grafana 开源组件构建了监控告警平台。最近一段时间在查询监控指标时遇到了性能瓶颈,表现为一些监控页面的图表加载特别慢,查询近7天的监控数据就会失败,极大的降低了开发人员的工作效率。

02

  排查

初步排查

选取其中一个加载失败的监控页面,查询近7天的监控数据,通过浏览器的开发者工具观察到的指标数据查询接口响应耗时如下图所示:

fc0f4245c1efae3bdf1ee5076b5a449b.png

分析指标数据查询接口和监控图表的对应关系后发现,监控图表加载失败是查询接口超时所导致的。使用超时的指标查询语句直接查询 Prometheus,即便将采样步长调高到40分钟,查询响应耗时依然有48秒之多。说明查询的主要耗时都用在 Prometheus 的查询处理上。

Prometheus查询处理流程分析

想要继续弄清楚 Prometheus 的查询处理为什么需要耗时这么久,我们需要简单了解一下 Prometheus 的查询处理流程。Prometheus 使用了一个基于标签(label)、值和时间戳的简单数据模型,这些标签和样本一起构成了数据序列(series),每个样本都是由时间戳和值组成。

f6d82cc72ad7ba03587090510bbc82e2.pngPrometheus 将这些数据存储在其内部的时间序列数据库中(Prometheus 也支持外部存储系统)。Prometheus 的数据库被划分为基本的存储单元,称为 block,其中包含一定时间范围(默认2小时)的数据。block 的结构如下图所示:

4e46abee8c3563fc3ec46da960f15a04.png

block 中最重要的两个组成部分是 chunks 和 index。chunks 中保存的是特定序列在一定时间范围内的采样集合,一个 chunk 只包含一个序列的数据。index 中保存的是 Prometheus 访问数据使用的索引信息。在 index 中保存着两种类的索引:postings index 和 series index。

  • postings index:保存着标签与包含该标签的序列之间的对应关系。例如,标签 __name__ ="logback_events_total" 可以被包含在两个序列中,logback_events_total {job="app1", level="error"}和 logback_events_total {job="app2", level="error"}。

  • series index:保存着序列和 chunk 之间的对应关系。例如,序列 {__name__=”logback_events_total”, job=”app1”, level="error"} 可能保存在00001和00002两个 chunk 里。

block 中还包含了一个 meta.json 文件(保存 block 的元数据信息)和 一个 tombstones 文件(保存已经删除的序列以及关于它们的信息)。

Prometheus 的查询处理通常包含以下五个基本步骤:

1、通过查询的时间范围确定对应的 block。

2、通过 postings index 确定与标签匹配的序列。

3、通过 series index 确定这些序列对应的 chunk。

4、从这些 chunk 中检索样本数据。

5、如果查询中包含操作符、聚合操作或内置函数,还需要基于样本数据进行二次计算。

详细排查

了解了 Prometheus 的查询处理流程后,我们可以得出以下结论:

1、查询的时间范围越大则耗时也就会越多,因为查询时间范围越大则涉及的 block 也会越多。

2、标签的值越多则查询耗时也就会越多,因为标签每增加一个值就会生成一个新的序列。

3、查询中使用了操作符、聚合操作或内置函数也会增加耗时,因为需要基于样本数据进行二次计算。

为了后面描述方便,我们先引入一个定义:基数(cardinality)。基数的基本定义是指一个给定集合中的元素的数量。以logback_events_total 这个指标为例,我们来理解下Prometheus 中标签基数和指标基数。

3620cd9b95d798d87af8080a536cc26b.pnglogback_events_total 指标有两个标签,其中标签 job 有两个值,那么它的基数为2,同理 level 标签的基数为5,logback_events_total 指标的基数为10。指标基数越高查询耗时也就会越多。

理解了基数的定义后,我们选取一个查询超时的监控指标来进行基数分析。先看下这个指标的一条标签数据:

http_server_requests_seconds_count{application="app1", cluster="cluster1", exception="xxxException", instance="xxx", job="app1", method="GET", returnCode="A0000", status="200", uri="/xxx"}

执行如下 PromQL(Prometheus自定义的数据查询语言) 来查询该指标每个标签的基数(用实际标签名替换下面语句中的 label_name):

count(count by (label_name) (http_server_requests_seconds_count))

该指标的标签基数汇总如下:

2d2762aaa4dcf0d4f341ddb9781a0899.png可以看到,instance 和uri 这两个标签的基数都很高。执行如下 PromQL 查询该指标的基数,发现该指标的基数达到了147610。

count({__name__="http_server_requests_seconds_count"})

用同样的方式分析了下其他问题指标,指标基数同样达到了10万以上。作为对比,我们抽样分析了几个加载比较快的指标,指标基数大都在1万以下。因此可以确认,查询耗时高主要是指标基数过高引起的。实际监控图表配置的查询语句中还使用了一些聚合操作(例如 sum)和内置函数(例如 rate),也在一定程度上增加了查询耗时。

03

  优化

Prometheus 提供了一种叫做记录规则(Recording Rule)的方式来优化我们的查询语句,记录规则的基本思想是:预先计算经常要用或计算开销较大的表达式,并将其结果保存为一组新的时间序列。以上面提到的 http_server_requests_seconds_count 这个指标为例,优化前的一个监控图表的查询语句如下:

sum(rate(http_server_requests_seconds_count{application="$application", cluster=~"$cluster", uri!~"/actuator/.*|/\\*.*|root|/|/health/check"}[1m])) by (uri)

从查询语句可以看出,该监控图表依赖于 application、cluster 和 uri 这三个标签的聚合数据,因此可以创建如下的记录规则(记录规则的详细创建方式可以参考 Prometheus 官方文档):

record: http_server_requests_seconds_count:rate:1m:acu

expr: sum(rate(http_server_requests_seconds_count{uri !~ "/actuator/.*|/\\*.*|root|/|/health/check"}[1m])) by (application,cluster,uri)

记录规则创建后默认只包含记录规则创建时间之后的数据,并不包含创建之前的历史数据。Prometheus从 v2.27 版本开始支持通过命令行指令来手工回溯历史数据(对于 Prometheus v2.38及以下版本,需要在实例启动时开启--storage.tsdb.allow-overlapping-blocks 参数),通过 promtool tsdb create-blocks-from rules --help 可以了解该指令的使用,这里给出了一个该指令的样例:

promtool tsdb create-blocks-from rules \

--start 1680348042 \

--end 1682421642 \

--url http://mypromserver.com:9090 \

rules.yaml

promtool tsdb create-blocks-from rules 命令的输出是一个目录(默认是 data/ ),其中包含了记录规则文件中所有规则历史数据的 block。为了让新生成的 block 生效,必须将它们手工移动到正在运行的 Prometheus 实例数据目录下。移动后,新产生的 block 将在下一次压缩运行时与现有 block 合并。

在执行完上面的操作后通过 PromQL 查询这个记录规则的基数,发现指标基数下降到了4878。原来监控图表的查询语句可以调整为:

sum(http_server_requests_seconds_count:rate:1m:acu{application="$application", cluster=~"$cluster"}) by (uri)

对优化后的监控图表进行测试,效果对比如下图所示,可以看到查询的时间范围越长,效果提升越明显。这主要得益于记录规则带来的指标基数大幅降低以及函数计算的预先处理。

cc7d49681451b212238cad55a22a2e38.png在实际场景中,如果有多个监控图表都用到了同一个监控指标,可以整体评估一下记录规则应该怎么创建。因为一个记录规则也是一组时间序列,在满足查询需求的前提下尽量避免创建过多的记录规则。

04

  小结

当 Prometheus 指标基数过高时,就会出现监控图表加载很慢甚至加载失败。通过 Prometheus 提供的记录规则,我们可以对查询语句进行优化从而减少查询耗时。除了记录规则外,还有一些技巧可以优化查询性能,例如增加 Prometheus 指标采集间隔,删除不用的指标序列等。实际上,在监控指标设计阶段就应该对指标基数进行评估,必要时对标签取值进行取舍。例如,一个标签对应 HTTP 响应码,可以将它的取值定义为 1XX、2XX、3XX、4XX、5XX,相比详细的响应码可以大大降低指标基数。

608d9f8aed19761f44c778b62d6d2bd0.jpeg

也许你还想看

会员接口治理的探索与实践

组件化设计在会员业务的应用和实践

会员测试环境治理之路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArcGIS创建渔网Create Fishnet工具生成指定大小格网

本文介绍在ArcMap软件中,通过“Create Fishnet”工具创建渔网,从而获得指定大小的矢量格网数据的方法。 首先,我们在创建渔网前,需要指定渔网覆盖的范围。这里我们就以四川省为例,在这一范围内创建渔网;其中…

prometheus实战之四:alertmanager的部署和配置

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是《prometheus实战》系列的第四篇,在《prometheus实战之三:告警规则》中曾经提到过,整个告警功能分为规则和…

基于AT89C51单片机的并入串出乘法口诀的设计与仿真

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87779146?spm1001.2014.3001.5503 源码获取 并入串出乘法口诀的设计与仿真系统设计 目录 第一章 概述 3 1.1课题研究及意义 3 1.2课题设计内容 4 第二章系统设计…

FE_Vue学习笔记 路由基本使用

1 路由的简介- router 路由【route】就是一组key-value的对应关系。 多个路由,需要经过路由器【router】的管理。 SPA (single page web application)应用 - 单页面web应用【一个index.html】 1)单页Web应用(single page web a…

Linux快照太有趣了!

1.首先介绍一下什么是Linux快照 VMware 的菜单栏中有虚拟机快照这个选项,形象来说快照就相当于一个备份文件,记录的是虚拟机运行到某一节点时的状态,在虚拟机的使用过程中如果发生了意外,比如系统崩溃或系统异常,此时…

python字典(一)——defaultdict的学习

一、前言 本页主要用来记录python字典的一些知识 二、Python中的defaultdict的详解 2.1defaultdict返回的默认值 defaultdict顾名思义默认字典,这个字典属于普通字典的一个子集,是对普通字典的改进 dcit的使用: 当访问字典里面不存在的key时会…

leetcode:相对名次(详解)

前言:内容包括-题目,代码实现,大致思路,代码解读 目录 题目: 代码实现: 大致思路: 代码解读: part 1:开辟返回数组 part 2:score数组的每个元素及其下标…

视觉大模型DINOv2:自我监督学习的新领域

如果你对自监督学习感兴趣,可能听说过Facebook人工智能的DINO(无标签知识蒸馏)。我们在以前的文章中也介绍过它。DINOv2不仅是一个新版本而且带来了新的改进,并为判别性自监督学习设定了更高的标准。当然公司的名字也从Facebook变为了Meta。 本文将介绍…

成功打破 GPT-4 上限,新版 Claude 横空出世!

公众号关注 “GitHubDaily” 设为 “星标”,每天带你逛 GitHub! 前 OpenAI 团队成员在离职后,创办了 Anthropic 公司。今年 3 月份的时候,该公司推出一款名为 Claude 的应用,试图与 ChatGPT 一争高下。 一个多月过去了…

分享Python采集77个css3代码,总有一款适合您

分享Python采集77个css3代码,总有一款适合您 Python采集的77个css3代码下载链接:https://pan.baidu.com/s/13EiUDXOAZvvKmF2KGrivzA?pwdubb2 提取码:ubb2 两款漂亮的bootstrap分页样式 纯CSS3用户卡片设计效果 4种炫酷CSS3 loading预加…

第六十章 Unity 发布Web平台

WebGL 是一种用于在 Web 浏览器中渲染图形的 API,基于 OpenGL ES 图形库的功能。WebGL 1.0 大致与 OpenGL ES 2.0 功能相匹配,而 WebGL 2.0 大致与 OpenGL ES 3.0 功能相匹配。WebGL 构建选项允许 Unity 将内容发布为 JavaScript 程序,而这些…

FastDFS+Nginx - 本地搭建文件服务器同时实现在外远程访问「端口映射」(1)

大家好,我是晓星航。今天为大家带来的是面向对象编程相关的讲解!😀 文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Ngi…

ARM 处理器模式(二)

文章目录 ARM 处理器模式工作模式模式切换内核寄存器各个模式对应的内核寄存器 ARM 处理器模式 ARMv7-a 处理器共有 9 种工作模式 工作模式 User:用户模式,非特权模式,大部分程序运行的时候就处于此模式FIQ:快速中断模式&#x…

算法修炼之练气篇——练气二十二层

博主:命运之光 专栏:算法修炼之练气篇 前言:每天练习五道题,炼气篇大概会练习200道题左右,题目有C语言网上的题,也有洛谷上面的题,题目简单适合新手入门。(代码都是命运之光自己写的…

Vue列表展示计数器【第二篇】

&#x1f331; 1、vue列表展示案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>vueDemo02列表展示</title> </head> <body> <div id"xy"><!--原始展示方式…

2023最新CleanMyMac中文版系统清理优化工具

CleanMyMac中文版功能非常的强大&#xff0c;操作简单&#xff0c;使用起来高效快捷&#xff0c;软件自身拥有一个安全数据&#xff0c;且拥有一定的规格&#xff0c;CleanMyMac中文版能够确定软件能够正确选择和清理Mac垃圾文件&#xff0c;更加安全&#xff0c;可靠。一键快速…

thinkPhP6.0安装教程图解--PHP框架安装

ThinkPhP 6.0 安装 1.环境检查 首先&#xff0c;thinkphp6.0&#xff0c;要求php的环境是7.2.5及以上的&#xff0c;所以先检查自己的php环境是否符合要求。 在cmd命令窗口中输入php -v 或者没有配置环境变量的话&#xff0c;可以在php编辑器中输出php_info()或则PHP_VERSIO…

记录一次异常:feign异常--NoSuchBeanDefinitionException: No qualifying bean of type

1、完整报错 2023-06-29 16:17:28.127 WARN 3732 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyExcep…

JetCache 使用简单案例到源码解析读这一篇就够

背景 github.com/alibaba/jet… 一、使用方法&#xff1a; 1. 创建项目— 此处使用springboot项目 2. 引入starter <dependency> <groupId>com.alicp.jetcache</groupId> <artifactId>jetcache-starter-redis</artifactId><version>2…

Servlet3.0 新特性全解

Servlet3.0新特性全解 tomcat 7以上的版本都支持Servlet 3.0 Servlet 3.0 新增特性 注解支持&#xff1b;Servlet、Filter、Listener无需在web.xml中进行配置&#xff0c;可以通过对应注解进行配置&#xff1b;支持Web模块&#xff1b;Servlet异步处理&#xff1b;文件上传AP…