【博客675】prometheus生产上易犯的错误

news2024/10/6 22:29:17

prometheus生产上易犯的错误

Mistake 1: Cardinality bombs

这是每个人在开始使用 Prometheus 时至少会遇到一次的经典陷阱。一旦您发现 Prometheus 基于标签的数据模型的有用性,您可能会想按各种有用的标签维度来拆分指标,直到您创建的时间序列超出 Prometheus 服务器可以处理的数量。

例如,您可能有一个 HTTP 服务器公开一个由 HTTP 方法分割的请求计数器:

http_requests_total{method="POST"}
http_requests_total{method="GET"}
http_requests_total{method="PUT"}
http_requests_total{method="DELETE"}

这完全没问题,只要您确保仅在method标签中存储有效的方法值即可。然而,也许现在您想到了通过请求用户的 ID 来有效地分割指标:

http_requests_total{method="POST",user_id="1"}
http_requests_total{method="POST",user_id="2"}
http_requests_total{method="POST",user_id="3"}
[…many more…]
http_requests_total{method="POST",user_id="16434313"}

http_requests_total{method="GET",user_id="1"}
http_requests_total{method="GET",user_id="2"}
http_requests_total{method="GET",user_id="3"}
[…many more…]
http_requests_total{method="GET",user_id="16434313"}
[…many more…]

假设您拥有多个用户,您现在将遭受基数爆炸,这将导致 Prometheus 服务器的内存使用量达到 OOM(内存不足)崩溃的程度。

因此请始终记住:指标上的每一个独特的标签组合都会自动创建一个时间序列,Prometheus 必须摄取、索引、存储和处理该时间序列。虽然对于可以放入单个标签中的值的数量没有绝对的硬性限制,但您需要保持在 Prometheus 服务器可以处理的时间序列的总预算之内。例如,大型 Prometheus 服务器可能能够处理多达几百万个时间序列,因此您需要选择标签的组合、它们所在的指标以及相应地公开这些指标的目标数量,以便您保持在该服务器的时间序列总预算范围内。

特别是,您需要避免存储无界的高基数值,例如:

  • 公共 IP 地址或电子邮件地址
  • 完整的 HTTP 路径,如果这些路径包含 ID 或其他无界基数信息
  • 进程 ID(除非严格限制到特定集合)

有时,您可以通过减少标签值的基数来解决标签的高基数问题,而无需完全删除它,同时仍然保留最有用的信息。例如,对于表单的 HTTP 路径/api/users/739567637385/posts/28388445,您至少可以用最终标签值中的占位符替换路径的最高基数组件(本例中的用户和帖子 ID),以生成更通用的模式,例如生成/api/users/{user_id}/posts/{post_id}方式更少的不同标签值和时间序列。

Mistake 2: Aggregating away valuable labels in alerting expressions

在编写聚合整个服务的警报表达式时,一个常见的诱惑是聚合掉您不需要立即需要的任何标签来确定是否存在问题。例如,如果您想确定服务的总体错误率(跨所有标签维度)是否太高,您可以编写如下规则:

sum(rate(errors_total{job="my-job"}[5m])) > 10

默认情况下,sum()聚合器生成不带任何标签的单个输出系列。这不仅会删除您实际想要聚合的维度(例如实例、错误类型等),还会删除所有输入系列中常见的所有标签,这些标签稍后可能对路由或消除警报有用。警报管理器。特别是job标签(或等效的服务分组标签)是常见的路由标签,因为作业通常与负责处理其警报的团队相关联。因此,建议尽可能在聚合中保留此标签:

sum by(job) (rate(errors_total{job="my-job"}[5m])) > 10

更好的选择是通过使用聚合修饰符将聚合修饰符替换为排除列表方法来保留您不想显式删除的任何标签:by()without()

sum without(instance, type) (rate(errors_total{job="my-job"}[5m])) > 10

这样,输入系列上您未明确聚合的任何标签仍可在 Alertmanager 中用于警报聚合和路由,以及帮助您了解警报的来源。

Mistake 3: Using unscoped, “naked” selectors

编写 PromQL 查询(尤其是警报!)时,您需要格外小心,仅从要为其编写查询的作业或服务中选择数据。多个不相关的服务可能会公开相同的指标名称,甚至可能具有完全不同的语义含义。即使您最初编写查询时情况并非如此,明天可能会出现指标名称冲突的新服务,从而完全破坏您的警报规则或仪表板。
为了避免意外提取不相关作业的数据的情况,请务必使用标签匹配器来确定选择器的范围,该标签匹配器明确命名您所引用的作业或服务。通常,这就是job标签。

例如,不安全的“裸”选择器可能会从您不期望的其他作业中选择具有相同指标名称的数据:

rate(errors_total[5m]) > 10

更安全的范围选择器会将所选指标限制为来自作业的指标my-job:

rate(errors_total{job="my-job"}[5m]) > 10

通过这种方式,您还可以避免出现以下情况:一旦刮掉另一个产生指标名称冲突的服务,您的警报规则或仪表板就会开始出现异常行为。

Mistake 4: No for duration in alerting rules

警报规则中的字段for允许您指定输出时间序列需要在连续的规则评估周期中存在多长时间才能从待处理警报转变为触发警报。这本质上允许您向警报规则添加每个系列的时间容差。现在您可能想知道哪些警报应该有for持续时间,以及应该持续多长时间。在大多数警报中完全省略持续时间可能是个好主意吗for?

考虑一个警报规则,该规则使用up指标来查找无法成功抓取的目标,并省略可选for修饰符:

alert: InstanceDown
expr: up == 0

一次失败的抓取(这很容易发生)将导致此规则触发。通常,您会希望让警报规则不那么容易触发,并在通知人员之前至少等待几分钟以查看问题是否仍然存在:

alert: InstanceDown
expr: up == 0
for: 5m  # An instance needs to be down / unreachable for 5 minutes before creating an alert for it.

对于已经内置了一些时间平均的警报表达式来说,不指定for持续时间甚至可能会出现问题。请考虑此警报的高错误率:

alert: HighErrorRate
expr: rate(my_errors_total{job="my-job"}[5m]) > 10

此规则将在第一次评估时触发,其中错误率较高( 5 分钟可用数据的平均值)。虽然 5 分钟平均值已经引入了一些鲁棒性,但请考虑当 Prometheus 服务器完全新鲜或一段时间没有收集数据时会发生什么:

  • 5 分钟rate()窗口将仅考虑一些最近的样本,而不是实际平均超过五分钟的数据。
  • 该规则现在可以为甚至还没有五分钟数据的系列立即生成警报。

引入for持续时间可以解决此问题:

alert: HighErrorRate
expr: rate(my_errors_total{job="my-job"}[5m]) > 10
for: 5m

对于大多数警报规则也可以提出类似的论点。因此,为了使您的警报规则更加强大,您几乎总是希望将for持续时间设置为至少几分钟。请记住,这也会导致警报反应时间变慢for,因此找到时间容差的平衡点很重要。

Mistake 5: Too short rate() windows

当在太短的时间窗口内计算速率时,您是否曾经因间隙或完全空的图表而感到沮丧,例如rate(my_counter[1m])?rate()和其他 PromQL 函数(如increase()、irate()、deriv())告诉您时间序列在给定时间窗口内上升或下降的速度,都需要在输入时间窗口下至少有两个样本才能告诉您该序列在之间的发展情况这两个样本。如果您将时间窗口设置得太小,则可能会面临窗口下只有 1 个或 0 个样本的风险,在这种情况下,输出将变为空。

例如,如果您采用rate()每 15 秒抓取一次的 20 秒范围内的计数器指标,则很有可能这 20 秒通常不会覆盖两个样本,因此您会得到一个间隙率:

在这里插入图片描述
采取极端的方式:如果将速率窗口减少到 16 秒,当两个相隔 15 秒的点碰巧落在任意对齐的 16 秒窗口下时,您只会偶尔获得输出点:

在这里插入图片描述
如果进一步减小窗口,您最终将根本没有机会覆盖两个样本,因此您会得到完全空的查询输出:

在这里插入图片描述
因此,您需要选择足够大的输入窗口 - 不仅仅是 2 倍的抓取间隔,而且您还希望在面对偶尔的抓取失败和不幸的窗口对齐时保持稳健。通常,选择速率窗口大小至少为抓取间隔的 4 倍是一个好习惯:
在这里插入图片描述

提示:使用Grafana时,您还可以使用$__rate_interval模板变量自动为您选择一个安全间隔。

Mistake 6: Using rate() and friends with the wrong metric type

虽然 PromQL 以其他一些方式进行静态类型化,但它无法直接告诉您是否将错误类型的指标传递到并非旨在处理该错误的函数中。最突出的例子是:

  • Using rate() with gauge metrics

    rate()、irate()和函数increase()被设计为仅与计数器度量一起使用。计数器是跟踪累积计数的指标,这些计数只会增加(而不会减少),除非0跟踪过程重新启动时偶尔重置。为了在速率计算中尽可能抵消计数器重置,这些函数尝试将提供的时间窗口下样本值的任何减少解释为重置并对其进行补偿(另请参阅我们有关速率计算的详细文章)。这种计数器重置检测和补偿意味着您只能0从这些功能中获得积极的结果(或 )。如果您不小心传递了一个可以自然上升的计量指标如果下降(如内存使用情况),PromQL 将无法分辨出此错误,而只会返回不正确的输出值。这是因为每次您的仪表指标下降时,rate()都会将其解释为计数器重置,并会错误地“纠正”它。

  • Using deriv() with counter metrics

    您可以将该deriv()函数视为大致相当于rate(),但对于仪表而言。deriv()告诉您在输入时间窗口内测量的仪表指标每秒上升或下降的速度。虽然不常见,但与rate()这里相同的陷阱可能会以另一种方式击中您:由于该deriv()函数没有实现有关计数器重置的任何逻辑(仪表没有这些!),尝试计算deriv()计数器指标将给出每当在提供的窗口下重置计数器时,您都会得到错误的结果,有时甚至是负面的结果。

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

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

相关文章

【QT】枚举用到的宏详解:Q_ENUM,Q_FLAG,Q_DECLARE_FLAGS,Q_DECLARE_OPERATORS_FOR_FLAGS

目录 1. Q_ENUM宏 与 QMetaEnum类1.1 Q_ENUM宏的作用1.2 使用Q_ENUM注意的问题1.3 在写有关枚举的代码时,我们可能遇到这种情况:需要用到枚举的字符串,该怎么办?1.4 下面通过一段简单的代码来说明Q_ENUM的作用 2. Q_FLAG宏2.1 Q_F…

【SpringMVC】| 拦截器(含源码分析)

目录 拦截器 1. 拦截器的介绍 2. 拦截器的三个抽象方法 3. 拦截器的使用 4. 多个拦截器的执行顺序 Java核心技术大会 文末福利(Java核心技术卷) 拦截器 拦截器能拦截请求,前面学习的过滤器也能拦截请求,那两者有什么区别…

【数据结构与算法C++实现】1、异或的用法

原视频为左程云的B站教学 文章目录 1 异或换值2 求出数组中唯一一个出现奇数次的数3 求出数组中的两个出现奇数次的数 异或: 相同为0,不同为1。 更好的记忆方式: 不进位相加 10010 ^ 01100--------11110性质 0 ^ N N,N ^ N 0…

广电用户画像分析之根据用户行为数据进行筛选与标签添加

在数据处理和分析领域,我们经常需要根据用户的行为数据进行筛选和标签添加,以便更好地理解用户行为和偏好。在本篇博客中,我们将介绍两个示例,展示如何根据用户的收视行为数据和订单信息进行数据处理和分析。 前情提要&#xff1…

创新型影像测量仪器有哪些

走新型工业化之路,加快重塑竞争新优势,离不开更强的创新能力、更高的创新效率。新型工业化道路的基本标志和落脚点是要做到“科技含量高、经济效益好、资源消耗低、环境污染少、人力资源优势得到充分发挥”,并实现这几方面的兼顾和统一。而不…

spring boot 项目实现打包依赖分离

spring boot version 2.7 (理论上是通用的)Maven version 3 打包结果 重要文件以及文件夹解释 lib: 存在当前项目的全部依赖 other:和当前项目的 groupID 不同的依赖 project:和当前项目groupID 相同的依赖 XX-3.0.0-SNAPSHOT.j…

jdk安装及配置

一、下载安装包: 阿里云盘分享 提取码:am66 双击该程序 点击下一步 稍作等待即可。 二、配置环境变量 再新建一个系统变量CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar 找到Path变量,双击编辑 Path变量。点击新建&…

【深度学习】GPT-2

在GPT1问世不久,和GPT很相似的BERT横空出世,并且在各方面都超越GPT-1。OpenAI在《Language Models are Unsupervised Multitask Learners》中于2019年提出的GPT-2,全称为Generative Pre-Training 2.0。提出语言模型式无监督的多任务学习 &…

DDS 信号发生器实验

目录 DDS 信号发生器实验 1、DDS 简介 2、实验任务 3、程序设计 3.1、DDS 顶层模块代码 3.2、clk_wiz IP 核 3.3、ILA IP 核(集成逻辑分析器:Integrated Logic Analyzer,ILA) 3.4、各波形参考代码 3.4.1、正弦信号波形采…

身份识别与访问管理(IAM)工具

AD360 是一款企业 IAM 解决方案,可帮助管理身份、保护访问并确保合规性。它具有强大的功能,例如自动化身份生命周期管理、安全 SSO、自适应 MFA、基于审批的工作流、UBA 驱动的身份威胁防护和历史审计报告。AD360 直观的界面和强大的功能使其成为满足现代…

行业云统领2023十大技术趋势,新华三把脉数实融合演进路径

“每一年的科技突破与环境变局,有一定的随机性又有一定的必然性,导致人类社会永远处于动态塑形的过程。”中国工程院院士陈晓红在想像未来的技术变化时认为:“无论怎么变化,人类未来图景仍然源于社会生活与经济发展的真实需求”。…

了解MySQL配置文件:位置、结构和选项

目录 1 MySQL配置文件的位置2 MySQL配置文件的结构3 MySQL配置选项4 [mysqld]部分:5 [client]部分:6 MySQL配置文件的重要性7 总结 本文详细介绍了MySQL配置文件的位置、结构和常用选项。了解如何使用MySQL配置文件来管理和配置MySQL服务器的行为和属性。…

5. QT环境下使用OPenCV(基于TCP实现摄像头图像数据的多线程传输)

1. 说明 通常情况下对于图像数据的采集可以放在后端进行,采集到的图像数据如果有需要可以通过通信将数据传输到前端进行显示,这其中需要使用到TCP数据传输协议和QT下的多线程开发技术。QT当中主线程一般是界面层次的,在主线程中执行耗时较长的数据操作,会引起界面的卡顿,…

React学习9 Router6

使用 userRoutes路由表 注册路由 Outlet指定路由组件呈现位置 ***很重要,userNavigate()实现编程式路由导航 函数式组件接收params参数的hook useParams() 接受search参数 接收state参数 userNavigate 实现前进后退 判断是否处于路由组件中,在路由器管理…

网站加密防止拷贝的php域名授权方法

1 public function getdata()2 $method DES-ECB;//加密方法3 $passwd qq496631085;//加密密钥4 $options 0;//数据格式选项(可选)5 $iv ;//加密初始化向量(可选)6 $url ba…

双因素身份验证在远程访问中的重要性

在快速发展的数字环境中,远程访问计算机和其他设备已成为企业运营的必要条件。无论是在家庭办公室运营的小型初创公司,还是团队分散在全球各地的跨国公司,远程访问解决方案都能保证工作效率和连接性,能够跨越距离和时间的阻碍。 …

MQTT(二)Java整合MQTT

Java整合MQTT 上一节知道MQTT是一个通信协议,需要一个代理服务Broker;通信设备作为客户端Client,后台系统服务器也作为客户端Client。 经过了解选用EMQX作为代理服务Broker(支持WEB界面查看) 后台服务使用Spring In…

【教学类-36-01】Midjounery生成的四张图片切片成四张小图

作品展示: 把一张正方形图片的四个等大小图切割成四张图片 背景需求 最近在学习ChatGPT的绘画(midjounery AI艺术) 我想给中班孩子找卡通动物图片(黑白线条),打印下来,孩子们练习描边、涂色…

【发布】ChatGLM2-6B:性能大幅提升,8-32k上下文,推理提速42%

自3月14日发布以来, ChatGLM-6B 深受广大开发者喜爱,截至 6 月24日,来自 Huggingface 上的下载量已经超过 300w。 为了更进一步促进大模型开源社区的发展,我们再次升级 ChatGLM-6B,发布 ChatGLM2-6B 。 在主要评估LLM模…

《C++ Primer》--学习7

顺序容器 容器库概览 迭代器 与容器一样,迭代器有着公共的接口:如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的。 迭代器范围 一个迭代器范围是由一对迭代器表示,两个迭代器分别指向…