功能
-
存儲agent push的數據
-
為query 提供查詢數據接口
參考RRDtool的理念,在數據每次存入的時候,會自動進行采樣、歸檔。在默認的歸檔策略,一分鍾push一次的頻率下,
歷史數據保存5年。同時為了不丟失信息量,數據歸檔的時候,會按照平均值采樣、最大值采樣、最小值采樣存三份。
用戶在查詢某個metric,在過去一年的歷史數據時,Graph會選擇最合適的采樣頻率,返回采樣過后的數據,提高了數據查詢速度。
配置文件
{
"debug": false, //true or false, 是否開啟debug日志
"http": {
"enabled": true, //true or false, 表示是否開啟該http端口,該端口為控制端口,主要用來對graph發送控制命令、統計命令、debug命令
"listen": "0.0.0.0:6071" //表示監聽的http端口
},
"rpc": {
"enabled": true, //true or false, 表示是否開啟該rpc端口,該端口為數據接收端口
"listen": "0.0.0.0:6070" //表示監聽的rpc端口
},
"rrd": {
"storage": "/home/work/data/6070" //絕對路徑,歷史數據的文件存儲路徑(如有必要,請修改為合適的路)
},
"db": {
"dsn": "root:@tcp(127.0.0.1:3306)/graph?loc=Local&parseTime=true", //MySQL的連接信息,默認用戶名是root,密碼為空,host為127.0.0.1,database為graph(如有必要,請修改)
"maxIdle": 4 //MySQL連接池配置,連接池允許的最大連接數,保持默認即可
},
"callTimeout": 5000, //RPC調用超時時間,單位ms
"migrate": { //擴容graph時歷史數據自動遷移
"enabled": false, //true or false, 表示graph是否處於數據遷移狀態
"concurrency": 2, //數據遷移時的並發連接數,建議保持默認
"replicas": 500, //這是一致性hash算法需要的節點副本數量,建議不要變更,保持默認即可(必須和transfer的配置中保持一致)
"cluster": { //未擴容前老的graph實例列表
"graph-00" : "127.0.0.1:6070"
}
}
}
默認端口
-
http:6071 提供graph本身的管理功能API
-
rpc:6070 用於接收transfer push 的分片數據和為query提供查詢接口
存儲過程
-
接收數據
接收到transfer push的數據之后,按rrd數據庫解析數據,計算出UUID和MD5,計算方式為:
* item.UUID = item.endpoint + item.metric + item.tags + item.dstype + item.step * item.md5 = item.endpoint + item.metric + item.tags
-
處理數據
graph會將item進行三種處理
-
刷入本地緩存,即內存隊列中,定期將隊列中的數據存儲到rrd文件,rrd命名規則:RRDFileName = rrd_base_path + item.md5 + item.dstype + item.step
-
建立本地索引,首先會嘗試增量建立索引,當索引接受到數據后,通過數據的checksum值來確定是不是這個來自endpoint的metric是否是第一次采集數據。如果不是第一次采集數據,
-
則在indexedItemCache中能夠找到,並且如果uuid沒變則只更新item。如果uuid變了重新index操作(涉及dstype和step的改變)。
如果是第一次數據采集,在indexeditemCache中找不到,添加到unindexeditemCache中,等待被索引。最后定時會unindexeditemCache中創建索引,保存到mysql數據庫中,此時涉及mysql數據庫三張表
* endpoint 表。該表記錄了所有上報數據的endpoint,並且為每一個endpoint生成一個id即 endpoint_id。
* tag_endpoint表。拆解item的每一個tag。用tag和endpoint形成一個主鍵的表。記錄每個endpoint包含的tag。每條記錄生成一個id,為tagendpoint_id
* endpoint_counter表。counter是metric和tags組合后的名詞
mysql> desc endpoint;
+----------+------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+-------------------+-----------------------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| endpoint | varchar(255) | NO | UNI | | |
| ts | int(11) | YES | | NULL | |
| t_create | datetime | NO | | NULL | |
| t_modify | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+----------+------------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
mysql> desc endpoint_counter ;
+-------------+------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+-------------------+-----------------------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| endpoint_id | int(10) unsigned | NO | MUL | NULL | |
| counter | varchar(255) | NO | | | |
| step | int(11) | NO | | 60 | |
| type | varchar(16) | NO | | NULL | |
| ts | int(11) | YES | | NULL | |
| t_create | datetime | NO | | NULL | |
| t_modify | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+------------------+------+-----+-------------------+-----------------------------+
8 rows in set (0.00 sec)
mysql> desc tag_endpoint;
+-------------+------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+-------------------+-----------------------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| tag | varchar(255) | NO | MUL | | |
| endpoint_id | int(10) unsigned | NO | | NULL | |
| ts | int(11) | YES | | NULL | |
| t_create | datetime | NO | | NULL | |
| t_modify | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+------------------+------+-----+-------------------+-----------------------------+
6 rows in set (0.00 sec)
建立索引的目的是為了更快定位rrd文件,而rrd文件命名是受endpoint、metric、tags、dstype、step決定的,所以當查詢請求時,不可能便利所有的rrd文件,會先讀取數據表的數據,拼接出rrd文件路徑,然后根據時間范圍進行獲取數據
- 存入實時數據(HistoryCache,雖然叫history,但是其實只保存了每個指標的最近3份數據)
查詢過程
-
根據endpoint和counter,從索引中獲取dsType和step
-
生成md5 :endpoint + counter => md5
-
從indexedItemCache查找md5對應的item
-
沒有找到的話,從DB中進行查找
-
-
開始/結束時間,按照step進行取整
-
根據endpoint、counter、dsType、step,獲取對應的RRD文件名
-
從cache中查詢數據 :根據cache key獲取items和flag
-
從歷史數據中查詢數據,如果cfg支持migrate,以及判斷查詢數據不在這個Graph實例,則從其它Graph實例進行查詢。否則,查詢本地rrd文件
-
將cache中的數據,以及rrd/其它Graph實例中的數據,進行合並
數據遷移過程
Graph模塊支持在集群成員改變的情況下,將其它Graph模塊的數據拉取過來,或者向其它Graph模塊發送本地的數據,達到數據遷移的目的。
配置:
"migrate": {
"enabled": false,
"concurrency": 2,
"replicas": 500,
"cluster": {
"graph-00" : "127.0.0.1:6070"
}
}
字段含義為:
-
enabled:是否啟動遷移功能
-
concurrency:每個一致性哈希節點,負責遷移數據的工作協程數
-
replicas:一致性哈希中,每份數據的重復數
-
cluster:節點名稱以及具體IP端口