写点什么

Prometheus Remote Storage 实践

  • 2020-03-05
  • 本文字数:2458 字

    阅读完需:约 8 分钟

Prometheus Remote Storage 实践

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!

Prometheus 的设计者非常看重监控系统自身的稳定性,所以 Prometheus 仅仅依赖了本地文件系统,而这就决定了 Prometheus 自身并不适合存储长期数据。


“长期”具体是多久,需要根据具体的数据量和服务器资源来看。如果数据不过期,最先达到瓶颈的资源通常是内存,因为 Prometheus 会将需要的 time series 都先读到内存,所以一个时间范围长,涉及 time series 非常多的 query 很容易触发 OOM。

为什么 Prometheus 需要 Remote Storage

Prometheus 起初打算寻找一个合适的外部存储,但发现现有的时序数据库都不能很好地满足 Prometheus 的要求。


详见 Prometheus issue 史上的 #10:


https://github.com/prometheus/prometheus/issues/10


所以 Prometheus 提供了 remote read 和 remote write 的接口,让用户自己去实现对接。

Prometheus 的 remote read 和 remote writes


Prometheus doc 中对 Prometheus 与外部系统集成方式


Adapter 是一个中间组件,Prometheus 与 Adapter 之间通过由 Prometheus 定义的标准格式发送和接收数据。Adapter 与外部存储系统之间的通信可以自定义。目前 Prometheus 和 Adapter 之间通过 grpc 通信。Prometheus 将 samples 发送到 Adapter。为了提高效率,samples 会在队列中先缓存,再打包发送给 Adapter。而一个读请求中包含了 start_timestamp,end_timestamp 和 label_matchers,response 则包含所有 match 到的 time series 。也就是说,Prometheus 仅通过 Adapter 来获取时间序列,进一步的处理都在 Prometheus 中完成。



Prometheus v2.0.0 中 RemoteWriteConfig 结构


Prometheus v2.0.0 中 RemoteWriteConfig 的结构定义了数据发送给 Remote Storage 的方式。尽管在官方文档中 remote read 和 remote write 的配置还没有稳定,我们还是可以从代码中来一探究竟。HTTPClientConfig 可以用来配置 HTTP 相关的 auth 信息,proxy 方式,以及 tls。WriteRelabelConfigs 用在发送过程中对 timeseries 进行 relabel。QueueConfig 定义了发送队列的 batch size,queue 数量,发送失败时的重试次数与等待时间等参数。默认的 QueueConfig 如下:



默认的 QueueConfig


可以看到 Prometheus 默认定义了 1000 个 queue,batch size 为 100,预期可以达到 1M samples/s 的发送速率。Prometheus 输出了一些 queue 相关的指标,例如 failed_samples_total, dropped_samples_total,如果这两个指标的 rate 大于 0,就需要说明 Remote Storage 出现了问题导致发送失败,或者队列满了导致 samples 被丢弃掉。


再来看看 RemoteReadConfig 结构:



RemoteReadConfig 结构


ReadRecent 如果为 false,Prometheus 会在处理查询时比较本地存储中最早的数据的 timestamp 与 query 的 start timestamp,如果发现需要的数据都在本地存储中,则会跳过对 Remote Storage 的查询。


这是一个比较重要的优化,详情可见 #3129:


https://github.com/prometheus/prometheus/pull/3129

Prometheus 与 Influxdb

Prometheus 与 Influxdb 之间的数据格式转化很方便,所以 Prometheus 与 Influxdb 的对接也是比价简单的。Influxdb 官方提供了用来对接 Prometheus 的 read 和 write api,所以 Adapter 可以去掉。遗憾的是 Influxdb 集群不再开源。所以本文中也就没有过多去探究 Influxdb。


Read and Write api:


https://github.com/influxdata/influxdb/pull/8784

Prometheus 与 Opentsdb

Opentsdb 是一个基于 hbase 的分布式时序数据库。它的一大优势便是长期保存大量数据,并且能够水平扩展。本文中使用的 Opentsdb 版本是 v2.3.0。


Opentsdb 中的 sample 格式为:



sys.cpu.user 是指标名,host=webserver01 是其中一个 tag,类似于 Prometheus 中的 label,1356998400 是时间戳(unix timestamp,精度为秒或毫秒),50 是值(支持 8 byte 整数或单精度浮点数,在 2.4 及之后的版本中会支持双精度浮点数)。


将 Prometheus 的数据写入 Opentsdb 需要注意以下几点:


  • Metric name 和 tag value 需要 escape。Opentsdb 对 metric name 和 tag value 的约束比 Prometheus 更严格。Prometheus 的 remote_storage_adapter 中定义了一些 escape 规则。

  • Prometheus 中 timestamp 精度默认为毫秒,在 Opentsdb 中则需要开启相应的配置项才能支持毫秒。但如果 scrapeinterval 是 10s 级别的话,秒级精度也足够了。

  • Opentsdb 有 tag 数的限制,默认为 20。可以通过 tsd.storage.max_tags 来配置。


Prometheus 的 remote_storage_adapter 不支持从 Opentsdb 中读取数据。为了查询 Opentsdb 中存储的数据,可以直接使用 grafana。


下图是在 grafana 中分别从 Opentsdb 和 Prometheus 查询同样的指标得到的结果:



我们也可以自己实现一个 Adapter,以支持 Prometheus 从 Opentsdb 直接读取数据。根据前面对 Prometheus read 协议的描述,只需要实现 “=”, “!=”, “=~”, “!~” 这四种 matcher。”=” 和 “!=” 可以转化为 Opentsdb 中的 “literal_or” filter。而 “=~” 和 “!~” 没有办法直接转化成 filter,只能先转化成 match all, 从 Opentsdb 中查出数据然后再过滤(这样可能会导致 OOM,但是一般来说还有其它 filter,加上 downsample,可以让返回的数据量不至于过大)。


下面是两个 Prometheus:


  • 一个仅从 local storage 读取数据(同时向 Opentsdb 写数据);

  • 另一个仅从 Opentsdb 读数据,执行相同的查询得到的结果对比。


可以看到从 remoteread 的查询速度相对较慢,但结果是基本一致的:



prometheus 从 local storage 读取数据



Prometheus 从 Remote Storage 读取数据


用 Opentsdb 来作为 Prometheus 的长期存储可以说是一个比较可靠的方案。另外有许多其它的时序数据库也提供了对 Prometheus 的集成,详见:


https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage


关于 Opentsdb 的 schema,可参考:


http://opentsdb.net/docs/build/html/user_guide/backends/hbase.html


https://yq.aliyun.com/articles/54785


本文转载自才云 Caicloud 公众号。


原文链接:https://mp.weixin.qq.com/s/DYTMTgVO6LhWgTnhgNmybQ


2020-03-05 16:092255

评论

发布
暂无评论
发现更多内容

架构师系列之7:分布式领域的CAP理论

桃花原记

微服务架构的认知思考

橘子皮嚼着不脆

架构师训练营第一期第十周作业

Leo乐

极客大学架构师训练营

Netty源码解析 -- FastThreadLocal与HashedWheelTimer

binecy

源码 Netty

周练习 10

何毅曦

第六周作业

晴空万里

第十周作业

Meow

架构师训练营 week6 学习总结

花果山

极客大学架构师训练营

week1总结

ルンルン

诗意地栖居在赛博世界:人间烟火中的EMUI设计美学

脑极体

CAP原理

Sandman

极客大学架构师训练营

week10作业

龙卷风

架构师一期

第十周总结

orchid9

架构是训练营第 10 周作业

郎哲158

架构师训练营第一期第十周总结

Leo乐

极客大学架构师训练营

Dubbo微服务调用的时序图

天天向上

极客大学架构师训练营

第十周作业

极客大学架构师训练营

架构师训练营第二期 Week 6 作业

bigxiang

极客大学架构师训练营

架构师训练营第二期 Week 6 总结

bigxiang

极客大学架构师训练营

架构师训练营 - 第十周 - 作业一

行者

DDD中的模型

zamkai

领域驱动设计

第十周总结

Meow

微服务架构及Dubbo 微服务调用的时序图

garlic

极客大学架构师训练营

Elasticsearch配置和集群维护

Rayzh

ELK 日志 Elastic Stack

架构师训练营第十周作业

Shunyi

极客大学架构师训练营

架构师训练营 week6 课后作业

花果山

极客大学架构师训练营

架构训练营第六周作业

一期一会

分布式系统

第十周作业

Geek_ce484f

极客大学架构师训练营

万字长文,助你深度遨游Spring循环依赖源码实现!

Java spring 编程

第十周作业总结

Geek_ce484f

极客大学架构师训练营

架构是训练营第 10 周学习笔记

郎哲158

Prometheus Remote Storage 实践_文化 & 方法_才云科技_InfoQ精选文章