文章采集器哪个好用(给出一个基于全部是prometheus的multi_remote_read方案)
优采云 发布时间: 2022-01-28 14:12文章采集器哪个好用(给出一个基于全部是prometheus的multi_remote_read方案)
视频教程的前言今天会写一篇文章文章来分析federation的问题,并给出一个基于所有prometheus的multi_remote_read方案架构图
联邦问题 联邦使用示例
scrape_configs:
- job_name: 'federate'
scrape_interval: 15s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job="prometheus"}'
- '{__name__=~"job:.*"}'
static_configs:
- targets:
- 'source-prometheus-1:9090'
- 'source-prometheus-2:9090'
- 'source-prometheus-3:9090'
看看上面的示例配置,作为采集的配置感觉如何?
// web.go 的 federate Handler
router.Get("/federate", readyf(httputil.CompressionHandler{
Handler: http.HandlerFunc(h.federation),
}.ServeHTTP))
分析下,联邦功能是读取本地存储数据处理。
func (h *Handler) federation(w http.ResponseWriter, req *http.Request) {
// localstorage 的query
q, 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.SeriesSet
set := storage.NewMergeSeriesSet(sets, storage.ChainedSeriesMerge)
// 遍历存储中的full series
for 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 := false
globalUsed := 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()
}
如果没有过滤,那么分片的数据只是凑在一起,正确使用联邦的姿势是没有意义的,剩下的数据可以保存在本地采集器这样,pre-可以在每个federation上进行aggregation和alert,提高查询速度默认prometheus不支持下采样。实现统一查询的正确方法是使用prometheus multi_remote_read。remote_read 支持读写的存储是什么,但这和我们今天要讲的问题有什么关系呢?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
上面的配置代表两个后端存储并发查询,查询结果可以mergeprometheus remote_read prometheus可以感觉很多人不知道这个特性,以为remote_read必须配置第三方存储如m3db等,所以可以结合以上两个特点使用多个采集prometheus+多个无状态prometheus查询实现prometheus的高可用方案数据复制,这个方案有什么缺点
并发查询必须等待最慢的一个返回,所以如果有慢节点,查询速度就会下降,例如
在处理繁重的查询时,查询可能会挂起
因为是无差别的并发查询,也就是说所有的查询都会被定向到所有的采集器s,这会导致一些采集器s总是查询这里不存在的数据。
如果想准确的发送查询到数据及其存储分片,可以参考我之前写的路由方案:开源项目:prome-route:使用反向代理实现prometheus分片
您可以添加一些逻辑来检测/管理采集器 以改进此解决方案