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上的内容。
      这一次又是一个教训!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值