作者 | 浪子燕青燕小乙

来源 | https://zhuanlan.zhihu.com/p/368868988

前言

  • 我看到很多人会这样使用联邦:联邦 prometheus 收集多个采集器的数据

  • 实在看不下下去了,很多小白还在乱用prometheus的联邦

  • 其实很多人是想实现 prometheus 数据的可用性,数据分片保存,有个统一的查询地方(小白中的联邦 prometheus)

  • 而且引入 m3db 等支持集群的 tsdb 可能比较重

  • 具体问题可以看我之前写的文章 m3db 资源开销,聚合降采样,查询限制等注意事项[1]

    • m3db-node oom 追踪和内存分配器代码查看[2]

  • 今天写篇文章分析下联邦的问题,并给出一个基于全部是 prometheus 的multi_remote_read方案

架构图

腾讯试点强制6点下班!标志着反996、反内卷的第一枪吗?

联邦问题

  • 联邦文档地址[3]

联邦使用样例

  • 本质上就是采集级联

  • 说白了就是 a 从 b,c,d 那里再采集数据过来

  • 可以搭配 match 指定只拉取某些指标

  • 下面就是官方文档给出的样例

scrape_configs:- job_name: 'federate'scrape_interval: 15shonor_labels: truemetrics_path: '/federate'params:'match[]':- '{job="prometheus"}'- '{__name__=~"job:.*"}'static_configs:- targets:- 'source-prometheus-1:9090'- 'source-prometheus-2:9090'- 'source-prometheus-3:9090'

看上面的样例配置怎么感觉是采集的配置呢

  • 不用怀疑就是,下面看看代码分析一下 从上述配置可以看到采集的 path 是 /federate

// web.go 的 federate Handlerrouter.Get("/federate", readyf(httputil.CompressionHandler{Handler: http.HandlerFunc(h.federation),}.ServeHTTP))

分析下联邦函数 说白了就是读取本地存储数据处理

func (h *Handler) federation(w http.ResponseWriter, req *http.Request) {// localstorage 的queryq, err := h.localStorage.Querier(req.Context(), mint, maxt)defer q.Close()// 最终发送的Vector 数组vec := make(promql.Vector, 0, 8000)hints := &storage.SelectHints{Start: mint, End: maxt}var sets []storage.SeriesSetset := storage.NewMergeSeriesSet(sets, storage.ChainedSeriesMerge)// 遍历存储中的full seriesfor set.Next() {s := set.At()vec = append(vec, promql.Sample{Metric: s.Labels(),Point:  promql.Point{T: t, V: v},})for _, s := range vec {nameSeen := falseglobalUsed := map[string]struct{}{}protMetric := &dto.Metric{Untyped: &dto.Untyped{},}// Encode方法根据请求类型编码if protMetricFam != nil {if err := enc.Encode(protMetricFam); err != nil {federationErrors.Inc()level.Error(h.logger).Log("msg", "federation failed", "err", err)return}}}protMetric.TimestampMs = proto.Int64(s.T)protMetric.Untyped.Value = proto.Float64(s.V)protMetricFam.Metric = append(protMetricFam.Metric, protMetric)}//if protMetricFam != nil {if err := enc.Encode(protMetricFam); err != nil {federationErrors.Inc()level.Error(h.logger).Log("msg", "federation failed", "err", err)}}
}

最终调用压缩函数压缩

type CompressionHandler struct {Handler http.Handler
}// ServeHTTP adds compression to the original http.Handler's ServeHTTP() method.
func (c CompressionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {compWriter := newCompressedResponseWriter(writer, req)c.Handler.ServeHTTP(compWriter, req)compWriter.Close()
}

如果没有过滤那么只是一股脑把分片的数据集中到了一起,没意义。很多时候是因为数据量太大了,分散在多个采集器的数据是不能被一个联邦消化的。

正确使用联邦的姿势

  • 使用 match 加过滤,将采集数据分位两类

  • 第一类需要再聚合的数据,通过联邦收集在一起

    • 只收集中间件的数据的联邦 只收集业务数据的联邦

    • 举个例子

    • 其余数据保留在采集器本地即可

  • 这样可以在各个联邦上执行预聚合alert,使得查询速度提升

默认 prometheus 不支持降采样

  • 可以在联邦配置 scrape_interval 的时候设置的大一点来达到 模拟降采样的目的

  • 真实的降采样需要 agg 算法支持的,比如 5 分钟的数据算平均值、最大值、最小值保留,而不是这种把采集间隔调大到 5 分钟的随机选点逻辑

正确实现统一查询的姿势

什么是 remote_read

  • 简单说就是 prometheus 意识到自己本地存储不具备高可用性,所以通过支持第三方存储来补足这点的手段

  • 配置文档地址[4]

读写都支持的存储

  • AWS Timestream

  • Azure Data Explorer

  • Cortex

  • CrateDB

  • Google BigQuery

  • Google Cloud Spanner

  • InfluxDB[5]

  • IRONdb

  • M3DB[6]

  • PostgreSQL/TimescaleDB

  • QuasarDB

  • Splunk

  • Thanos

  • TiKV

但是这个和我们今天聊的问题关联在哪里?,往下看你就知道了

multi_remote_read

如果我们配置了多个 remote_read 接口的话即可实现 multi

remote_read:- url: "http://172.20.70.205:9090/api/v1/read"read_recent: true- url: "http://172.20.70.215:9090/api/v1/read"read_recent: true

上述配置代表并发查询两个后端存储,并可以对查询的结果进行 merge

merge 有啥用:你们的查询 promql 或者 alert 配置文件就无需关心数据到底存储在哪个存储里面 ,可以直接使用全局的聚合函数

prometheus 可以 remote_read prometheus 自己

感觉这个特点很多人不知道,以为 remoteread 必须配置第三方存储如 m3db 等,其实 p 也可以 remote_wirte 自己,只不过需要开启 --enable-feature=remote-write-receiver

高可用方案

所以结合上述两个特点就可以用多个采集的 prometheus + 多个无状态的 prometheus query 实现 prometheus 的高可用方案

  • 监控数据存储在多个采集器的本地,可以是机器上的 prometheus

  • 也可以是 k8s 中的 prometheus statefulset

  • prometheus query remote_read 填写多个prometheus的/api/v1/read/地址

数据重复怎么办

不用管,上面提到了 query 会做 merge,多个数据只会保留一份

可以利用这个特点模拟副本机制:

  • 重要的采集 job 由两个以上的采集 prometheus 采集

  • 查询的时候 merge 数据

  • 可以避免其中一个挂掉时没数据的问题

这种方案的缺点

并发查询必须要等最慢的那个返回才返回,所以如果有个慢的节点会导致查询速度下降,举个例子:

有个美东的节点,网络基础延迟是 1 秒,那么所有查询无论返回多快都必须叠加 1 秒的延迟。

应对重查询时可能会把 query 打挂。

但也正是这个特点,会很好的保护后端存储分片,重查询的基数分散给多个采集器了。

由于是无差别的并发 query,也就是说所有的 query 都会打向所有的采集器,会导致一些采集器总是查询不存在他这里的数据

那么一个关键性的问题就是,查询不存在这个 prometheus 的数据的资源开销到底是多少?据我观察,新版本速度还是很快的说明资源开销不会在很深的地方才判断出不属于我的数据。

m3db 有布隆过滤器来防止这个问题。

如果想精确把 query 打向数据它的存储分片可以参考我之前写的 route 方案:开源项目 : prome-route:使用反向代理实现 prometheus 分片[7]

主要哦,需要特征标签支持,并且数据天然就是分开的!!

忘了说了,这个方案还有个缺点就是重查询没控制好容易把你的采集器打挂了

脚注

[1]m3db 资源开销,聚合降采样,查询限制等注意事项: https://zhuanlan.zhihu.com/p/359551116

[2]m3db-node oom 追踪和内存分配器代码查看: https://zhuanlan.zhihu.com/p/183815841

[3]联邦文档地址: https://prometheus.io/docs/prometheus/latest/federation/

[4]配置文档地址: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read

[5]InfluxDB: https://docs.influxdata.com/influxdb/v1.8/supported_protocols/prometheus/

[6]M3DB: https://m3db.io/docs/integrations/prometheus/

[7]开源项目 : prome-route:使用反向代理实现 prometheus 分片: https://zhuanlan.zhihu.com/p/231914857

往期推荐

腾讯试点强制6点下班!标志着反996、反内卷的第一枪吗?

像Swing这种已经不太用的技术,大学还在教,到底要不要学?

改造了以前写的数据脱敏插件,更好用了

如何把Spring Boot的Jar包做成exe?超详细教程来了!

用好 Spring AOP,天降大锅从容应对!

喜欢本文欢迎转发,关注我订阅更多精彩

关注我回复「加群」,加入Spring技术交流群

别再乱用 Prometheus 联邦了,分享一个 Prometheus 高可用新方案相关推荐

  1. 春节将近,给大家分享一个抢高铁票抢票教程

    今天已经1.11号了,春节的脚步近了,但每年到这个时候最难的,莫过于一张回家的火车票. 据悉,今年春运期间,全国铁路发送旅客人次同比将增长 8.0% .达到 4.4 亿人次,2020 年铁路春运自 1 ...

  2. 分享一个共享充电线的方案技术

    从什么时候开始,共享这个词开始广泛进入我们的生活中.共享位置.共享文档.共享资源等关键词大范围且密集得出现在我们生活周围,而由此带来的一场共享经济革命也随之改变了我们的生活模式. 共享经济的核心是通过 ...

  3. swoole单台并发php,看到 swoole 又出黑料,忍不住分享一个 PHP 高并发方案

    坦白说,今天其实在看 deno 的资料,一直有考虑换语言了,或是 js,或是 lua 回归正题,这个高并发方案是基于 Serverless,参考 Laravel Vapor 的思路: 利用 Serve ...

  4. 支持m3u8的php视频cms,分享一个苹果CMS可用P2P的M3U8解析代码

    苹果CMS可用P2P的M3U8解析代码,非CDNbye的P2P.<?php /** * @代码开源,透明,请勿用于商业用途,完全开源模式,供大家一起探讨研究 * @支持全网(支持跨域)的M3U8 ...

  5. 分享一个漂亮的NetBeans配色方案

    [img]http://dl.iteye.com/upload/attachment/366386/4c8e1584-ca99-3b86-8d4b-d58b4fd79a04.png[/img] 下载后 ...

  6. 分享一个笑傲江湖高清服脚本辅助工具(以及随机数源码)

    游戏脚本基本只能做到和真实玩家一样的事情,只是不怕苦不怕累,能一直干活而已.由于不涉及修改游戏信息,因此也没有外挂的那些法律风险,而且上手也简单啊,毕竟我这种半路出家的都能用按键精灵之类的第三方软件去 ...

  7. 分享一个Vue前端代码质量检查方案

    质量降低导致的问题 开发效率会降低 出问题难以调试 维护体验差 项目不能保证足够的稳定 什么导致的代码质量降低 不在意代码质量, 只关注业务的产出 破窗效应 对好代码没概念 初步方案 代码风格要遵循V ...

  8. 技术分享:从双11看实时数仓Hologres高可用设计与实践

    简介:本文将会从阿里巴巴双11场景出发,分析实时数仓面临的高可用挑战以及针对性设计. 2021年阿里巴巴双11完美落下为帷幕,对消费者来说是一场购物盛宴,对背后的业务支撑技术人来说,更是一场年度大考. ...

  9. 分享一个美业微前端的落地方案

    2020年4月,有赞美业的前端团队历经7个月时间,完成了美业PC架构从单体SPA到微前端架构的设计.迁移工作.PPT在去年6月份就有了,现在再整理一下形成文章分享给大家. Part 01 " ...

最新文章

  1. 学了那么多年设计模式依然不会用!那可真蠢!
  2. 如何在优雅地Spring 中实现消息的发送和消费
  3. Gulp:自动化构建工具
  4. mtk camera 移植步骤
  5. linux内核_查看Linux内核版本
  6. 【AAAI 2018】腾讯 AI Lab 11篇论文精选:图像描述、NMT 模型、图卷积神经网络、DNN优化等
  7. 最大子段和 分治与动态规划
  8. java写spark碰到输出为[Ljava.lang.String;@889a8a8的情况
  9. bootstrap-validator 验证一个标签同时验证另一个指定标签
  10. C++ vector和list的区别及使用场景
  11. Fail - Fast机制
  12. opengl 保留上一帧_历史上第一部长片动画,还真有点重口
  13. 前序与中序遍历序列构造二叉树 中序与后序遍历序列构造二叉树
  14. Atitit 获取一列拼接为字符串 逗号分隔 目录1.1. Sql Group_contackt,但是排序只能拍一个的。。如果多个列对应排序则不行。。。 11.2. Js 使用map函数 1
  15. duilib在同一个界面中(xml)加载两种自定义的list
  16. EasyX基础入门——这一篇就够啦
  17. cam350怎么看顶层_CAM350常用快捷键
  18. 命主属性是水什么意思_八字五行属性查询表,有没有五行属性含水的且
  19. linux下组播遇到的问题及解决办法
  20. React Native Camera的新手教程

热门文章

  1. Node.js 0.8.21 稳定版发布
  2. SciTE for Ruby的配置
  3. Linux查找文件内容(grep)
  4. linux centos7 yum 报错 Public key for *.rpm is not installed 解决方法
  5. 内网渗透测试:隐藏通讯隧道技术(下)
  6. python3 多进程库 multiprocessing 使用简介
  7. win10 microsoft compatibility telemetry 禁用用户改善反馈服务进程 磁盘占用高
  8. python3 base64 加解密
  9. python 动态修改 类和实例 的方法
  10. linux c编译错误storage class specified for parameter XXX