前言
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期望的數據格式。
