Sensu Client是运行在其监控的App Server上的,主要工作有:
1. 订阅rabbitMQ消息,接收来自Server端的check任务,执行任务,并返回结果给Server端(通过rabbitMQ);
2. 周期性执行客户端standalone的check,并返回结果给Server端(通过rabbitMQ);
3. 监听TCP端口和UDP端口,接收来自外部的监控数据,返回给Server端(通过rabbitMQ);
Sensu Client实现很简单,只有两个ruby文件:process.rb和socket.rb。
其中大部分逻辑都在process.rb中实现,socket.rb主要处理来自外部输入的监控数据。
Sensu client启动的入口在:
sensu/bin/sensu-client
源码:
class="ruby" name="code">options = Sensu::CLI.read Sensu::Client::Process.run(options)
?
读取命令行参数,然后调用Process.run()
再看Process.run方法,在sensu/lib/sensu/client/process.rb文件
def self.run(options={}) client = self.new(options) EM::run do client.start client.setup_signal_traps end end
?
先实例化了一个Sensu.Client.Process对象,接下来EM事件循环里:启动client,设置信号处理。关于EM:http://blog.csdn.net/resouer/article/details/7975550
我们主要看看client.start
def start setup_transport setup_sockets bootstrap end
setup_transport是和rabbitMQ建立连接;
setup_sockets则是监听本地TCP端口和UDP端口以便接收来自外部的数据,具体看代码:sensu/lib/sensu/client/socket.rb,主要工作是接收外部数据,进行一系列的检查,通过后发送到rabbitMQ;
接下来看:bootstrap
def bootstrap setup_keepalives setup_subscriptions setup_standalone @state = :running end
?
setup_keepalives是为了使server端知道client是出于活动状态的一个周期性任务;
setup_subscriptions订阅rabbitMQ消息,当消息到来时,将消息解析成一个check,然后执行这个check并返回结果;
setup_standalone是启动一个定时任务执行standalone的check脚本(有些check不是从服务端订阅的,而是只是在某个客户端运行的)
最后将状态改成running
最后我们重点看下执行check命令
def execute_check_command(check) @logger.debug("attempting to execute check command", :check => check) unless @checks_in_progress.include?(check[:name]) # check是否已经在执行 @checks_in_progress << check[:name] # 加入check队列 command, unmatched_tokens = substitute_check_command_tokens(check) # 替换token??? if unmatched_tokens.empty? check[:executed] = Time.now.to_i # 执行时间 started = Time.now.to_f Spawn.process(command, :timeout => check[:timeout]) do |output, status| # 新建进程执行命令,有timeout check[:duration] = ("%.3f" % (Time.now.to_f - started)).to_f # 执行时间 check[:output] = output # 输出 check[:status] = status # 状态码 publish_check_result(check) # 发布执行结果 @checks_in_progress.delete(check[:name]) # 从执行队列中删除 end else # 如果有些token不匹配,直接报错 check[:output] = "Unmatched command tokens: " + unmatched_tokens.join(", ") check[:status] = 3 check[:handle] = false publish_check_result(check) @checks_in_progress.delete(check[:name]) end else @logger.warn("previous check command execution in progress", :check => check) end end
?
该方法执行了check命令,并将结果发布到rabbitMQ。