Sensu Client源码剖析

阅读更多

概述

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主要处理来自外部输入的监控数据。

Client的启动

Sensu client启动的入口在:
sensu/bin/sensu-client
源码:

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

最后我们重点看下执行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。

 
 

你可能感兴趣的:(sensu,ruby)