Grafana Labs 杰出工程师 Bryan Boreham 在 KubeCon 上详细介绍了他如何减少 Prometheus 的内存使用量。
本篇文章是「DevOps云学堂」与你共同进步的第 64篇
Prometheus 内存消耗是监视可观察性可能导致系统崩溃的众多方式之一。
Grafana Labs
的杰出工程师Bryan Boreham
在 KubeCon+CloudNativeCon
的演讲中详细介绍了他如何尝试各种方法以最终减少Prometheus的内存使用量
。他演讲的标题是Prometheus 如何将内存使用减半
,讲述了他对 Prometheus 的研究,特别是标签的内存消耗,揭示了减少内存消耗的方法。
根据Prometheus 文档,标签用于区分正在测量的事物的特征:
**operation=create|update|delete**
stage=extract|transform|load
Boreham 的工作也本着开源精神,展示了贡献如何能够带来真正的成果。在两年的时间里,向监控系统项目提出了 30 个 Pull 请求,修改了 2,500 多行代码
,Boreham 的工作帮助最新版本的 Prometheus 使用量是之前版本的一半。
这是一条漫长的道路,但最终非常令人满意。有数十万台 Prometheus 服务器在运行,通过降低内存需求,我们降低了运行它们的成本及其碳足迹。--Boreham 在
KubeCon+CloudNativeCon
之后告诉The New Stack
Boreham 在演讲中解释说, Go编程语言在运行时有一个内置的分析器,可以提供 Prometheus 内存以及 CPU 使用情况的内存消耗细分。它提供了所谓的可视化火焰图视图
。块的宽度是正在使用的内存量的比例。Boreham 表示,上图顶部显示 100%,总共 6.7 GB 的内存消耗。
所谓的sawtooth效应在图表中发挥作用。Boreham 告诉 The New Stack,垃圾随着时间的推移不断积累,然后被收集,因此内存急剧下降,然后又重新积累。这就是sawtooth
Go 内存分析器报告上次垃圾回收时的内存使用情况,因此,您在这张图片中永远不会看到垃圾。很多人认为,‘哦,这可能主要是垃圾,我不需要考虑它’。但是当你查看 Go 的配置文件时,这绝不是垃圾。这是sawtooth的底部,是不能丢弃的。
减少内存消耗的过程首先要问,‘好吧,是什么让它变得这么大?
。但总体而言,获胜者是大约两年前的情况,Prometheus 内部几乎三分之一的内存都被标签
占用了(图中为 31%)。
Boreham 解释说,Prometheus 中的每个系列(Series)都由这个名称/值对集唯一标识。如果你有另一个相关的系列,唯一的区别在于方法之间,你实际上会得到一套全新的字符串,等等。“所以,你看着这个,你会说,好吧,这很愚蠢。我只有一份字符串,但事情并没有那么简单。”
上图展示了里面的数据结构。指向所有标签的切片标头为 24 字节
,每个字符串都有一个 16 字节的字符串标头
。它是一个指向内容和长度的指针, 如果你把它们全部加起来,就会发现数据结构中的所有这些指针都比字符串本身大得多。
使用Prometheus PR 10991,Boreham 将所有字符串放入一个字符串中,并用长度对它们进行编码:
花了一年的时间,更改了 2,500 行代码,因为有大量代码只是假设它知道数据结构是什么样的
在 Prometheus 2.74.2
中,虽然之前的版本会在 17 GB
内存消耗时崩溃,但 Boreham 运行 2.47.2
,内存消耗为 13.1 GB
,没有发生任何事件:
虽然 2.47.2
中添加了样本处理
和原生直方图
功能,但“它们并没有真正耗尽所有内存,”Boreham 说,虽然内存消耗显着减少,但尚未完全达到50%
的水平然而。
Boreham 随后发现并修复了 2.39
中的一个错误:事务隔离环
,该错误“过去在某些条件下会变得巨大”,Boreham 说。“但我算了一下,内存消耗仍然没有完全减少一半”:
该错误修复将内存消耗减少至 10 GB
:
Boreham 继续研究 Go 分析器
,以瞄准内存消耗最大的罪魁祸首。
你选择最大的数字,然后研究它,如果可以的话,找到其中的一些低效之处,然后再做一遍。现在第二大数字现在是最大数字,一开始并没有那么大的数字现在已经是很大的数字了。所以这是一个很好的自我强化过程。
这是 2.47
加上上图中的所有 PR,总共 8.6 GB
内存消耗,几乎达到了 50%
的减少标记:
正如 Boreham 所解释的,Go 运行时中有一个参数叫做 GoGC
,它默认为 100
。sawtooth增长到的大小是sawtooth底部大小的 100%
,即 7 GB
。对于那些拥有 100 GB
Prometheus 的人来说,它增长了 50 GB
,但出于内务管理目的,您不需要 50 GB
的垃圾来运行有效的堆,你可以调整这个数字——它是一个你可以设置的环境变量,它会增长到你设置的百分比,超过它的最小值,并且垃圾收集速度会更快一些。
Prometheus
此后一直在 8 GB
内存下运行——内存消耗已达到 50%
。Boreham已经达到了他的目标:
Prometheus 用户将不可避免地欣赏较低的内存消耗,而大多数人可能对它是如何实现的不那么感兴趣。
但对于那些喜欢回馈开源社区的人来说,Boreham 的艰辛表明,只要付出大量的工作和耐心,就可以提出能够产生真正影响的拉取请求 (PR)。虽然Boreham的工作事后看来可能很简单,但显然并非如此——数学和科学研究中经常出现这种情况。Prometheus 以及一般的开源项目为用户和那些对计算感兴趣的人提供了做出改变的机会。
Boreham告诉 The New Stack
“这确实是一种爱的劳动,让计算机程序变得更小、更快对我来说是一种痴迷,所以能够将其用于如此受欢迎和广泛的项目真是太好了。而且,在 Grafana Labs,“开源是我们的 DNA。
您可以在此处观看 Boreham KubeCon 演示的完整视频:
https://youtu.be/29yKJ1312AM
文章翻译 https://thenewstack.io/30-pull-requests-later-prometheus-memory-use-is-cut-in-half/