武汉的开发者们注意啦!AI技术战略、框架以及最佳实战尽在Azure OpenAI Day 了解详情
写点什么

Prometheus Remote Storage 实践

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

    阅读完需:约 8 分钟

Prometheus Remote Storage 实践

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:092139

评论

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

悲观锁与乐观锁的实现(详情图解)

Java架构师迁哥

破解class文件的第一步:深入理解JAVA Class文件

华为云开发者联盟

Java JVM 索引 class文件

Golang Test

escray

学习 极客时间 Go 语言 4月日更

聪明人的训练(二十三)

Changing Lin

4月日更

视频录制后有噪音怎么办?教你简答几步去除视频噪音!

奈奈的杂社

GitHub开源:4行代码实现《黑客帝国》数字雨特效

不脱发的程序猿

GitHub 开源 程序人生 4月日更 黑客帝国

阿里开发7年大牛:只需一篇文章吃透Android多线程技术,好文推荐

欢喜学安卓

android 程序员 面试 移动开发

插件化库VirtualAPK详解

寻找生命中的美好

android 插件化 VirtualAPK

理性看待区块链+大宗商品

CECBC

区块链

万字精华:好好巩固你的Nginx知识体系

学Java关注我

Java 编程 架构 程序人生 计算机

加密原理详解:对称式加密VS非对称式加密

Java架构师迁哥

Android组件化和插件化开发

寻找生命中的美好

android 组件化 插件化

使用CrossOver安装第三方软件

懒得勤快

线程的故事:我的3位母亲成就了优秀的我!

王磊

Java 线程 多线程

开发知识 | 即时通讯是怎么做到的?

YonBuilder低代码开发平台

大前端 即时通讯 APP开发 小程序制作 开发技巧

阿里巴巴的“双11”高并发秒杀终极版教程!(Java语言设计)

Java 编程 程序员 架构

LeetCode题解:641. 设计循环双端队列,使用数组,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

谈谈 WebRTC 的 SDP Unified Plan

拍乐云Pano

WebRTC

架构实战营模块二作业

刁寿钧

架构实战营

走完线上 BUG 定位最后一公里

阿里巴巴中间件

可观测性 bug bug修复

饿了么EMonitor演进史

阿里巴巴中间件

可观测性 饿了么 emonitor etrace

合约跟单系统搭建,合约一键跟单app

开发环境上云,打造五星级开发体验

CODING DevOps

Kubernetes 云原生 CODING Nocalhost

泉州有了一个水务大脑,用AI守护“绿水青山”

百度大脑

AI

一周信创舆情观察(4.12~4.18)

统小信uos

redis常见应用场景

Sakura

4月日更

全网最全 ECMAScript 攻略

清秋

JavaScript ecmascript 大前端 ES6 Ecma

暴涨暴跌的牛市,普通人怎么和平发育?

CECBC

区块链

流程引擎介绍

上海派拉基础研发

流程

编曲新手可以用什么编曲软件?

奈奈的杂社

Rust从0到1-代码组织-模块

rust modules 模块

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