Bosh Health Monitor源代码
Bosh HealthMonitor(BHM)是Bosh里面的一个组件,负责收集BoshAgent收集到的各个组件的信息,比如cpu,mem,disk等。BHM有两种事件,一种是Bosh::Monitor::HeartBeat以及Bosh::Monitor::Alert。另外一个概念是plugin,在BHM里面有很多插件,这些插件负责具体地怎么去处理一个HeartBeat或者Alert事件。在health_monitor.yml文件中有一个plugins选项:
plugins:
- name: logger
events:
- alert
- name: tsdb
events:
- alert
- heartbeat
options:
host: 10.134.16.220
port: 4242
这个plugins选项负责设置某一个插件对什么事件感兴趣,比如tsdb选项对alert,heartbeat事件都感兴趣。
在源代码里面保存这样一个数组@plugins,这里保存了事件和插件的对应关系。
@plugins[''alert]=['logger','heartbeat'],当收到某一个事件的时候就比如alert时候,就会查询这个数组,然后分别调用相应logger的Plugin::process方法。
AgentManger类是负责管理所有客户端的agent以及deployments选项。
DirectorMonitor负责订阅hm.director.alert消息,观察director的声明周期,当director出现问题的时候,发生alert信息。HA的第四层可用性中会用到这点。
EventProcesser是所有插件处理器的一个通用接口,所有的事件经过这个处理器。然后调用各种各样的c插件。
在启动的时候AgentManger::setup_events时候,
@processor.add_plugin(lookup_plugin(plugin["name"],plugin["options"]), plugin["events"])
lookup_plugin会根据这个创建一个plugininstance。
订阅hm.agent.heartbeat.*,hm.agent.alert.*,hm.agent.shutdown.*等消息。
这些消息的处理函数都会调用AgentManger::process_event
process_event(kind,subject, payload = {})
kind—alert,heartbeart
subject—hm.agent.heartbeat.<agent_id> 提取最后一个字段就可以知道是那一个agent
case kind.to_s
然后根据消息的类型,调用相应的处理函数
when "alert"
on_alert(agent,message)
when "heartbeat"
on_heartbeat(agent,message)
when "shutdown"
on_shutdown(agent,message)
else
@logger.warn("Nohandler found for `#{kind}' event")
end
on_shutdown只是remove_agent将其从AgentManger::agents里面移除。
定时操作:
在启动的时候BHM会启动几个定时器操作。
EM.add_periodic_timer(@intervals.poll_director) { poll_director }
poll_director会从director获得deployment以及agent_id名称,然后根据AgentManger自身维护的@deployments以及@agent_id决定留下deployments以及agent_id
poll_director函数主要负责去director里面取出数据,填充到@agents,@developments里面
Dirrctor::fetch_deployments
eg:http://10.10.103.24:25555/deployments -> [{"name":"cf.hd"}]
获取部署的名称。
AgentManger::sync_deployments来同步deployments
sync_deployments把从director里面拿部署集群的名称,和在@deployments里面保存的名称进行比较,如果发现@deployments没有的staledeployment那么就从@deployments里面删除。同时从@agent里面删除这个staledeployment的所有agent。
AgentManger::sync_agents(deployment_name,vms)
Director::get_deployment_vms(deployment_name)获取部署名称所对应的vms,在get_deployment_vms获取的数据是这样的,eg:
[{"agent_id":"a3e91d0a-a5a3-41ca-abe3-57d256d28e45","cid":"vm-a34c83e0-209c-467c-8eec-e26470997a0c","job":"mysql_node_100","index":0},
{"agent_id":"11fd6005-5d84-4819-8d62-89a9cdd1c15b","cid":"vm-0c503d2a-f1cf-4685-a581-9744afcb3cf9","job":"dea","index":2},
{"agent_id":"16b9dddc-9c2d-426d-88e7-7aaaba703a65","cid":"vm-7d150ca7-4a19-4993-abf2-db654ed3853e","job":"stager","index":0},
@deployment[deployname][agentdid]这一系列数组。@deploymenst是一个Hashdeployment=>agentids
另外一个定时操作是analyze_agents
一次性分析所有agents
首先获取所有的#Agents from managed deployments
把AgentManger::@agent-@deployments.agent,对于这些多出来的agent
AgentManger.@agent[agent_id]---Bosh::Monitor::Agent
time_out?用现在的时间减去上次更新的时间(由hearbeat更新时间)如果大于在health_monitor.yml里面的agent_timeout的时间,那么就超时了
rogue?比较难理解
rogue?现在时间减去-@discovered_at如果超过了rogue_agent_alert时间并且未出现在任何deployment中,那么他就是rouge。@discovered_at是如何更新的?
在Agent.new的时候也更新@discovered_at
Agent.new在同步sync_agents时候出现,
在定期poll_director时候会出现,会根据poll_director的结果来更新@deployments,一切以poll_director的结果为基准,没有的就删除。
HeartBeat更新发现新的id会放在@agent里面
定期地analyze_agent
存储在@deployments存储的id和在@agent里面的id进行分析。
(@agents.keys.to_set -processed).each do |agent_id|
@logger.warn("Agent#{agent_id} is not a part of any deployment")
analyze_agent(agent_id)
count += 1
end
多出来的id就立刻进行分析,调用analyze_agent
发现新id,但是已经超时了,那么就发出一个alert事件。
如果发现这个agent_id没有存在任何deployment,也就是deployment为null,通过HeartBeat发现的新id都没有deployment,如果超过rogue_agent_alert时间那么就是rogue;