open-falcon transfer 模塊監控數據處理

       除了監控報警之外,監控系統的另外一種重要信息是監控數據。監控數據來源於主機的agent模塊,agent收集到主機的被監控的數據,實時上報給transfer模塊,tansfer模塊把信息及時反映給圖形界面模塊和監控數據判斷模塊。
   

1、源碼編譯transfer模塊

   1.1搭建環境

       安裝C語言、golang、mysql、redis、open-falcon環境等過程上一次已經在對alarm模塊報警信息處理的文章裏記錄過了,就不再重複記錄了。
  

   1.2編譯transfer源碼   

       進入transfer源碼目錄,命令行輸入如下內容回車:
  liang@ubuntu:~/goproj/src/github.com/open-falcon/transfer$ ./control build
       打印如下信息即編譯成功:
  0.0.14 190a7eb
       使用源代碼編譯方便以後可以按照自身的需求,自定義transfer的功能,如果沒有這樣的需求可以直接命令行安裝open-falcon,安裝完後修改配置文件,啓動各個模塊即可。
  

2、監控數據的傳遞過程

   2.1數據的來源

      監控數據來自於agent模塊,agent模塊收集到主機的各項數據後發送到transfer模塊,包括:內存使用情況、CPU使用情況、磁盤使用情況、磁盤IO情況、網絡使用情況、內核狀態、自定義數據等等。
 

   2.2數據的傳遞方法

      transfer模塊與agent模塊使用rpc的通信方式傳遞監控數據,agent發送rpc請求,包含:方法、參數。方法是transfer響應rpc請求的函數,參數是上傳的監控數據,以metric爲單位上傳,每一個metric對應一個監控指標。transfer接受rpc請求後,將會給agent返回一個rpc請求響應結果,agent即可得知監控數據是否上傳成功。
 

   2.3數據的接收過程   

      transfer模塊註冊監聽rpc請求的函數,定義該函數的參數爲結構體指針數組的形式,那麼,agent模塊傳入的請求方法使用的參數也是要對應爲數組的形式。agent模塊發送rpc請求後,transfer執行該函數,開始分析傳入的參數,最後返回rpc請求結果。
 

3、監控數據的分析過程

   3.1數據的分析過程

      open-flacon的官方文檔裏面可以得知,agent模塊上傳的監控數據項是以json的格式上傳,而且監控數據被保存在一個結構體指針數組裏面,每一個監控數據項是一個json格式結構體,一個數組包含多個json結構(即多個監控數據項),transfer拿到rpc請求參數後,遍歷該數組,拿到每一數組之後,按照json結構體格式進行分析,並且判斷關鍵項的值是否合法。最後,把每一項合法的json格式監控數據重新組織成數據結構體,再添加到另一個結構體指針裏面等待處理。
      

   3.2數據分析原函數

   open-falcon transfer模塊監控數據上傳rpc請求函數原型:  

      // process new metric values
func RecvMetricValues(args []*cmodel.MetricValue, reply *cmodel.TransferResponse, from string) error {
	start := time.Now()
	reply.Invalid = 0


	items := []*cmodel.MetaData{}
	for _, v := range args {
		if v == nil {
			reply.Invalid += 1
			continue
		}


		// 歷史遺留問題.
		// 老版本agent上報的metric=kernel.hostname的數據,其取值爲string類型,現在已經不支持了;所以,這裏硬編碼過濾掉
		if v.Metric == "kernel.hostname" {
			reply.Invalid += 1
			continue
		}


		if v.Metric == "" || v.Endpoint == "" {
			reply.Invalid += 1
			continue
		}


		if v.Type != g.COUNTER && v.Type != g.GAUGE && v.Type != g.DERIVE {
			reply.Invalid += 1
			continue
		}


		if v.Value == "" {
			reply.Invalid += 1
			continue
		}


		if v.Step <= 0 {
			reply.Invalid += 1
			continue
		}


		if len(v.Metric)+len(v.Tags) > 510 {
			reply.Invalid += 1
			continue
		}


		// TODO 呵呵,這裏需要再優雅一點
		now := start.Unix()
		if v.Timestamp <= 0 || v.Timestamp > now*2 {
			v.Timestamp = now
		}


		fv := &cmodel.MetaData{
			Metric:      v.Metric,
			Endpoint:    v.Endpoint,
			Timestamp:   v.Timestamp,
			Step:        v.Step,
			CounterType: v.Type,
			Tags:        cutils.DictedTagstring(v.Tags), //TODO tags鍵值對的個數,要做一下限制
		}


		valid := true
		var vv float64
		var err error


		switch cv := v.Value.(type) {
		case string:
			vv, err = strconv.ParseFloat(cv, 64)
			if err != nil {
				valid = false
			}
		case float64:
			vv = cv
		case int64:
			vv = float64(cv)
		default:
			valid = false
		}


		if !valid {
			reply.Invalid += 1
			continue
		}


		fv.Value = vv
		items = append(items, fv)
	}


	// statistics
	cnt := int64(len(items))
	proc.RecvCnt.IncrBy(cnt)
	if from == "rpc" {
		proc.RpcRecvCnt.IncrBy(cnt)
	} else if from == "http" {
		proc.HttpRecvCnt.IncrBy(cnt)
	}


	cfg := g.Config()


	if cfg.Graph.Enabled {
		sender.Push2GraphSendQueue(items, cfg.Graph.Migrating)
	}


	if cfg.Judge.Enabled {
		sender.Push2JudgeSendQueue(items)
	}


	reply.Message = "ok"
	reply.Total = len(args)
	reply.Latency = (time.Now().UnixNano() - start.UnixNano()) / 1000000


	return nil
}

4、使用netcat上傳數據

   4.1數據的上傳格式

      rpc請求函數中的參數,該參數使用json格式。

   4.2數據的上傳命令

      使用nc(netcate)網絡控制命令完成rpc請求
      echo "{\"method\":\"Transfer.Update\",\"params\":[[{\"endpoint\":\"bogon\",\"metric\":\"agent.test\",\"value\":2,\"step\":60,\"counterType\":\"GAUGE\",\"tags\":\"open-falocn\",\"timestamp\":123456789}]]}" | nc 192.168.12.88 8433
      這裏因爲rpc請求的傳入參數是結構體指針數組的形式,糾結了一段很長的時間,以後考慮問題一定要全面,既然使用到rpc請求,就要考慮到rpc請求函數的傳參問題,參數不對rpc請求肯定失敗。
 

5、使用socket上傳數據

   5.1數據的上傳格式

      rpc請求函數中的參數,該參數使用json格式。
 "{\"method\":\"Transfer.Update\",\"params\":[[{\"endpoint\":\"bogon\",\"metric\":\"agent.test\",\"value\":2,\"step\":60,\"counterType\":\"GAUGE\",\"tags\":\"open-falocn\",\"timestamp\":123456789}]]}"

   5.2數據的上傳過程

      一個socket客戶端,請求連接transfer監聽的rpc端口,發送rpc請求數據如上格式,接受rpc請求響應結果,關閉socket。
 這裏曾經嘗試了好多方法:libjrpc、libjson、golang、python、curl、openrpc、等都沒有實現。只能說生活狀態亂,工作效率也是很低下的。折騰了好長時間,一個簡單的socket就把數據發送過去了,真是淚崩,也是沒有完全理解當中的原理,一直埋頭看jsonrpc上的內容。
      這一次又是一個教訓!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章