Prometheus自定义远端存储实现

前言

prometheus默认把数据存在本地文件,随着时间的增长,文件会越来越大,当查询一个时间跨度很大指标时,会很消耗资源,查询效率会很低。

为此prometheus引入了远端存储。为了适应不同的远端存储,prometheus并没有选择对接各种存储,而是定义了一套读写存储接口,并引入了Adapter适配器,将prometheus的读写请求转化为第三方远端存储接口,从而完成数据读写。整体架构如下图:

远端接口规范

prometheus源码里提供了influxdb的远程读写实现,具体代码在

documentation/examples/remote_storage/remote_storage_adapter目录下,可以自己去看下,这里只讲下实现原理。

写接口

比如现在上报了一个指标:

df{instance="localhost:5000",job="prometheus",mount="/boot",step="15s"}

prometheus在向远端存储发起写请求时,都是采用HTTP的形式发送数据,数据格式如下:

{
	"timeseries": [{
		"labels": [{
			"name": "__name__",
			"value": "df"
		}, {
			"name": "instance",
			"value": "localhost:5000"
		}, {
			"name": "job",
			"value": "prometheus"
		}, {
			"name": "mount",
			"value": "/home"
		}, {
			"name": "step",
			"value": "15s"
		}],
		"samples": [{
			"value": 6,
			"timestamp": 1632204968206
		}]
	}]
}

适配器的写接口要做的就是把这个json格式的数据 写到我们自己的存储里。

读接口

现在我要查询一个指标:

df{mount="/boot"}

prometheus在调用远程存储的读接口时,会传入以下格式的参数:

{
	"queries": [{
		"start_timestamp_ms": 1632208558163,
		"end_timestamp_ms": 1632208858163,
		"matchers": [{
			"name": "mount",
			"value": "/boot"
		}, {
			"name": "__name__",
			"value": "df"
		}],
		"hints": {
			"start_ms": 1632208558163,
			"end_ms": 1632208858163
		}
	}]
}

再比如查询topk:

topk(3, rate(df[1m]))

对应的传参如下:

{
	"queries": [{
		"start_timestamp_ms": 1632216783085,
		"end_timestamp_ms": 1632217083085,
		"matchers": [{
			"name": "__name__",
			"value": "df"
		}],
		"hints": {
			"func": "rate",
			"start_ms": 1632217023085,
			"end_ms": 1632217083085,
			"range_ms": 60000
		}
	}]
}

而prometheus期望接口返回的数据格式如下:

{
	"results": [{
		"timeseries": [{
			"labels": [{
				"name": "instance",
				"value": "localhost:5000"
			}, {
				"name": "job",
				"value": "prometheus"
			}, {
				"name": "mount",
				"value": "/boot"
			}, {
				"name": "step",
				"value": "15s"
			}, {
				"name": "__name__",
				"value": "df"
			}],
			"samples": [{
				"value": 6,
				"timestamp": 1632208920000
			}, {
				"value": 4,
				"timestamp": 1632208950000
			}, {
				"value": 10,
				"timestamp": 1632208980000
			}, {
				"value": 10,
				"timestamp": 1632209010000
			}, {
				"value": 1,
				"timestamp": 1632209040000
			}, {
				"value": 9,
				"timestamp": 1632209070000
			}]
		}]
	}]
}

Demo

open-falcon是小米公司开源的一款监控工具,其后端采用rrd存储,rrd是一个时序数据库,以文件的形式存储在硬盘中,其特定为一个指标对应一个rrd文件,rrd文件固定大小为100kb左右,因为它采取了预聚合的方式,无论数据存多久,rrd文件大小都是固定不变的,在查询时间跨度很大的情况下,它会自动根据查询时间范围来选择聚合策略将数据返回给用户。

示例代码在 https://gitee.com/zqwlai/prometheus/tree/falcon-adapter/documentation/examples/remote_storage/falcon-adapter ,有兴趣的同学可以看下。

主要逻辑就是写数据时对接open-falcon的transfer模块,将数据写入,查询数据时从open-falcon的api模块获取。

总结

适配器的实现原理就是把prometheus的上报数据转换为远端存储自己的格式,读取数据时再把远端存储的数据转换为prometheus期望的数据格式。

posted @ 2021-09-21 15:53  独揽风月  阅读(798)  评论(0编辑  收藏  举报