prometheus remote-write解析(一) -- 使用

prometheus没有提供远程存储,但提供了远程存储的接口:

  • 远程存储只要实现这一接口,即可存储和读取prometheus的数据;
  • 这里仅分析remote-write:

笔者的prometheus被prometheus-operator部署在kubernetes中,kubernetes使用prometheus这个CRD管理配置,prometheus-operator监听到配置变化,将新配置apply到prometheus POD上。

prometheus CRD中的remote-write配置:

remoteWrite:
  - url: "https://1.2.3.4/api/monitor/v1/prom/write"
    tlsConfig:
      insecureSkipVerify: true

apply以后,prometheus生成如下的配置:

remote_write:
- url: https://1.2.3.4/api/monitor/v1/prom/write
  remote_timeout: 30s
  tls_config:
    insecure_skip_verify: true
  queue_config:
    capacity: 500
    max_shards: 1000
    min_shards: 1
    max_samples_per_send: 100
    batch_send_deadline: 5s
    min_backoff: 30ms
    max_backoff: 100ms

可以看到,它增加了queue_config,即传输过程中的队列配置。
假设每个remoteStorage使用1个queue进行传输:

  • queue中的初始shards数=min_shards,最大shards数=max_shards;
  • 每个shard的容量=capacity个sample;
  • 通过HTTP向remoteStorage发送数据时,若发送失败,则回退min_backoff;再次失败,则回退2*min_backoff,直到max_backoff;

prometheus的remote-write数据协议

prometheus的samples,经过protobuf的序列化,然后再经过snappy压缩,最后通过HTTP发送给remoteStorage;

对应的源代码:

// prometheus/storage/remote/queue_manager.go
func buildWriteRequest(samples []prompb.TimeSeries, buf []byte) ([]byte, int64, error) {
    var highest int64
    for _, ts := range samples {
        // At the moment we only ever append a TimeSeries with a single sample in it.
        if ts.Samples[0].Timestamp > highest {
            highest = ts.Samples[0].Timestamp
        }
    }
    req := &prompb.WriteRequest{
        Timeseries: samples,
    }

    data, err := proto.Marshal(req)
    if err != nil {
        return nil, highest, err
    }

    // snappy uses len() to see if it needs to allocate a new slice. Make the
    // buffer as long as possible.
    if buf != nil {
        buf = buf[0:cap(buf)]
    }
    compressed := snappy.Encode(buf, data)
    return compressed, highest, nil
}

remoteStorage如何实现remote-write协议接口

remoteStorage要实现remoteConfigs中定义的HTTP接口,这里主要参考influxdb的实现。
HTTP接口:

// 实现如下的API
Route{
            "prometheus-write", // Prometheus remote write
            "POST", "/api/v1/prom/write", false, true, h.servePromWrite,
        },

HTTP接口的实现:

func (h *Handler) servePromWrite(w http.ResponseWriter, r *http.Request, user meta.User) {
    ......
    var bs []byte
    if r.ContentLength > 0 {
        bs = make([]byte, 0, r.ContentLength)
    }
    body := r.Body
    buf := bytes.NewBuffer(bs)
    // 读request body
    _, err := buf.ReadFrom(body)
    // snappy解压缩
    reqBuf, err := snappy.Decode(nil, buf.Bytes())
    if err != nil {
        h.httpError(w, err.Error(), http.StatusBadRequest)
        return
    }
    // Convert the Prometheus remote write request to Influx Points
    var req remote.WriteRequest
    // protobuf反序列化
    if err := proto.Unmarshal(reqBuf, &req); err != nil {
        h.httpError(w, err.Error(), http.StatusBadRequest)
        return
    }
    ......
}

跟prometheus做的事情正好相反,这里先进行sappy的解压缩,然后再protobuf反序列化,得到真实的数据。

38 声望
21 粉丝
0 条评论
推荐阅读
cadvisor采集docker容器的DiskUsage指标--源码分析
一. DiskUsage指标cadvisor采集的docker容器的DiskUsage指标,包含:container_fs_inodes_freecontainer_fs_inodes_totalcontainer_fs_limit_bytescontainer_fs_usage_bytes {代码...} 二. 采集的过程docker容器...

a朋阅读 507

Helm3-安装RabbitMQ
最近在使用k8s搭建微服务时,发现需要手动修改yaml文件里面的pod name、pod image、svc name、ingress tls等等,非常麻烦,但是有了helm之后情况就不一样了,helm是k8s的包管理器,类似ubuntu的apt-get,centos的...

Awbeci阅读 9.5k

Kubernetes Gateway API 深入解读和落地指南
Kubernetes Gateway API 是 Kubernetes 1.18 版本引入的一种新的 API 规范,是 Kubernetes 官方正在开发的新的 API,Ingress 是 Kubernetes 已有的 API。Gateway API 会成为 Ingress 的下一代替代方案。Gateway A...

Rainbond2阅读 417

Jvm调优与微服务资源分配
在没有接触微服务之前,我们的java程序一般都部署在WebLogic、Tomcat这类应用服务器上,这些应用服务器本身也是基于Jvm虚拟机的。一般我们统一对应用服务器做Jvm参数调优(分配多大内存,线程池限制等),而不用...

KerryWu阅读 6.1k

K8S-使用Helm安装RabbitMQ和Redis的总结
记得去年2021上半年的时候自学了k8s并且使用helm安装了rabbitmq和redis,可以在开发、测试和生产环境上用起来,但是下半年之后就没有用,再拾起来的时候发现好多知识点都忘了,这篇文章就是总结使用helm安装rabbm...

Awbeci1阅读 1.9k

Kubernetes v1.27 新特性一览
Kubernetes v1.27 是 2023 年的第一个大版本更新,包含了近 60 项主要的更新。 而 1.26 只有 37 项,所以这个版本可以说是一个变化非常显著的版本了。

张晋涛1阅读 1.1k

封面图
实战:用“廉价”的NFS作为K8S后端存储
大家都知道,NFS是一种基于网络的文件系统协议,允许在不同的机器之间共享文件系统资源。在K8S中,可以使用NFS作为后端存储,以提供持久化存储和共享存储卷。但是否适合在生产环境使用NFS作为后端存储,这取决于...

不背锅运维2阅读 722

38 声望
21 粉丝
宣传栏