QuXiao's Blog

Life && Tech && Thoughts

Open-Falcon 源码阅读(二) HBS & Transfer

Written on

HBS

HeartBeat Server,顾名思义是接收所有Agent的心跳请求,用于在服务端注册Agent、更新Agent状态。后来HBS功能进一步扩展,从数据库中加载各种数据缓存起来,然后当Agent、Judge模块请求时,将数据返回给他们。

加载数据

HBS从数据库中加载了许多数据,如下表所示:

名称 含义 备注
GroupPlugins 主机组对应的Plugin(脚本)信息 select grp_id, dir from plugin_dir
GroupTemplates 主机组对应的模板 select grp_id, tpl_id from grp_tpl
HostGroupsMap 主机对应的主机组 select grp_id, host_id from grp_host
HostMap 主机名对应的主机ID select id, hostname from host
TemplateCache 主机对应的模板 select id, tpl_name, parent_id, action_id, create_user from tpl
Strategies 策略ID对应的策略内容 select s.id, s.metric, s.tags, s.func, s.op, s.right_value, s.max_step, s.priority, s.note, s.tpl_id from strategy as s where (s.run_begin='' and s.run_end='') or (s.run_begin <= now() and s.run_end > now())
HostTemplateIds 主机对应的模板 select a.tpl_id, b.host_id from grp_tpl as a inner join grp_host as b on a.grp_id=b.grp_id
ExpressionCache 全局的表达式 select id, expression, func, op, right_value, max_step, priority, note, action_id from expression where action_id>0 and pause=0
MonitoredHosts 主机ID对应的主机名称 select id, hostname from host where maintain_begin > now() or maintain_end < now()

Strategy Vs. Expression

上表中,大部分概念都是可以轻松理解的,不过Strategy和Expression这两个比较容易弄不清楚,Strategy和Expression在功能上有类似的地方,都是对于某些主机的某些采集指标进行判断,符合条件就执行相应的动作。

不过,Strategy需要依附于模板(Teamplate)存在,即模板是一个Strategy组,包含多个Strategy,模板可以与主机进行映射,也可以和主机组进行映射。另外,模板和模板之前也可以有继承关系。比如,模板T1包含判断CPU异常Strategy,模板T2包含判断网络异常Strategy,模板T3集成了T1和T2,这样T3就包含了T1和T2的所有异常判断Strategy。 而Expression则存在去全局的范围,也不需要划分为组的形式。

Strategy、Template与Expression的结构如下图所示:

当Strategy或者Expression判断出数据异常的时候,就是执行一个动作(Action),Action其实包含了一系列的动作,例如发送邮件、短信、通过URL执行Callback,还细化为在执行Callback之前/之后发送邮件、短信(虽然我认为这有些多此一举)。Action结构如下:

对外服务

HBS提供RPC和HTTP两大类服务(Open-Falcon的模块大部分均采用这种形式)。服务功能介绍总结如下表:

服务类型 服务名称 服务功能 备注
RPC Agent.MinePlugins 返回主机对应的插件列表 hostname -> hostid -> host_group -> plugin list
. Agent.ReportStatus 上报hostname,插入或更新host表  
. Agent.TrustableIps 返回配置中的信任IP列表  
. Agent.BuiltinMetrics 返回主机对应的采集指标参数,包括:侦听的端口、进程数、文件夹空间、URL可访问性 根据hostname查找到所属的主机组list,再找到所有template list,再查找哪些是('net.port.listen', 'proc.num', 'du.bs', 'url.check.health')这些的metric和tags
. Hbs.GetExpressions 返回全局的表达式  
. Hbs.GetStrategies 返回主机->策略列表的映射关系  
HTTP /health 返回固定字符串  
. /version 返回版本  
. /workdir 返回服务工作路径  
. /config/reload 发送reload请求  
. /expressions 返回表达式缓存  
. /plugins/ 返回某一个主机的Plugin  

Transfer

Transfer模块是一个『转发』模块,接收来自服务器发送的采集指标数据,进行一些简单的判断和处理之后,将数据转发至多个后端模块。

数据来源

Transfer的数据来源,一般有四种:

  1. Falcon-agent主动采集的基础监控数据。
  2. Falcon-agent执行用户自定义的插件返回的数据。
  3. client-library:线上的业务系统,都嵌入使用了统一的基础库,对于业务系统中每个业务接口,都会主动计算其qps、latency等指标,并上报。
  4. 用户产生的一些自定义的指标,由用户自行上报。

数据去向

Transfer支持的业务后端,有三种:Judge、Graph、OpenTSDB。Judge是我们开发的高性能告警判定组件,Graph是我们开发的高性能数据存储、归档、查询组件,OpenTSDB是开源的时间序列数据存储服务。

一致性哈希

一致性哈希是为了解决集群中机器宕机或者扩容造成的数据迁移问题。Transfer所连接的Judge和Graph模块,都是采用一致性哈希的形式组织成集群。每一个集群分为多个节点,每个节点又包含多个实例。

Hash key

一致性哈希的key是由收到的数据决定的。具体的,是由enpoint + metric + 排序之后的tags共同组成的字符串,代码如下所示:

之后,一致性哈希就可以根据hash key确定节点了。

数据转发流程

初始化

初始化连接池

模块启动时,会根据配置初始化RPC连接池。Judge模块初始化的连接池个数为Judge.Cluster。从代码中可以看出,每一个Cluster中的Judge模块进行的是单点部署。Graph模块初始化的连接池个数为Graph.Cluster中的地址数。

初始化发送队列

当Transfer接收到数据之后,跟根据一致性哈希确定节点,传递给相应的发送队列,队列中再去发送至Judge以及Graph模块。其中,发送给Judge模块一份数据(因为只配置了一个Judge实例),发送给所有属于该节点的所有Graph模块一份数据。 发送队列和连接池是一一对应的。

接收

Transfer模块有两种方式接收数据:原始TCP,和RPC。

原始TCP方式,Transfer与请求方保持长连接,数据之间通过 \n 分割,一共分为两中命令:"quit"和"update",前者为退出连接,后者为上报数据。

RPC方式,和Ping和Update方法,前者只会返回一个空response,后者为上报数据。

发送

通过原始TCP或者RPC方式接收到数据之后,会根据配置决定是否向Judge或Graph发送数据。 对于向Judge发送数据,首先会将数据转换为对应模块要求的格式,之后对于每一份数据(item),计算其key,找到一致性哈希中的节点node。通过node找到队列,将数据Push至队列尾部。 向Graph发送数据的逻辑和Judge的基本类似,区别就是找到一致性哈希的节点node之后,遍历该node中的所有地址addr,通过node + addr找到队列,将数据Push至队列尾部,一共发送了len(addr)份数据。

-- EOF --

comments powered by Disqus