NoOps

Ops make no ops | Ops的目标是没有Ops,嗯!

采用ruby+eventmachine+em-http-request实现一个站点可用性监控

作者: |   1,580 浏览  | 

采用ruby+eventmachine+em-http-request实现一个站点可用性监控。采用C/S的架构,将client部署在各个机房节点,定时探测域名并将结果返回给server,server将数据插入监控系统进行绘图和报警(注:我们使用zabbix)。

EventMachine,是类似python中的twisted的一个基于Reactor设计模式的事件驱动I/O框架,它可以很好的消除网络变成的复杂度,我们只需要在相应的方法中实现自己的业务逻辑,而不用去关心socket和线程等实现问题。

首先,构建一个简单的server:

然后我们再实现一下DemoServer:


在EM中定义了一些回调函数,我们可以根据我们的需要去实现这些方法,就可以在我们需要的阶段完成相对应的业务逻辑,如上例中:

  1. post_init: 一旦连接建立后它就会调用,如果我们想在连接建立后做些事情(如:保存对方的ip和端口信息或给对方发一段字符串等)
  2. unbind: 任何一端关闭连接,都会调用该函数。
  3. received: 无论何时我们从网络连接里接受到数据,该函数就会被调用。

上面的小例子,完成了一个监听在127.0.0.1:6000上的socketserver:

  • 当客户端连接完成时,输出客户端的ip和port
  • 当客户端断开连接时,若ip和port不为空,则输出断开client的ip和port,否则输出unknown client
  • 当服务端收到数据时,则直接将数据输出

由此可见,使用EM构建网络应用是件十分简单高效的事。

接下来讲讲em-http-request模块

em-http-request,是EM的一个http库,功能很强大,通过简单几行代码就可以完成http请求功能,目前官方列出的功能支持有:

  • Asynchronous HTTP API for single & parallel request execution
  • Keep-Alive and HTTP pipelining support
  • Auto-follow 3xx redirects with max depth
  • Automatic gzip & deflate decoding
  • Streaming response processing
  • Streaming file uploads
  • HTTP proxy and SOCKS5 support
  • Basic Auth & OAuth
  • Connection-level & Global middleware support
  • HTTP parser via http_parser.rb
  • Works wherever EventMachine runs: Rubinius, JRuby, MRI、

em-http-request使用起来十分简单, 举例如下:

上面的例子,是fiber+em-http的例子:

  1. http = EventMachine::HttpRequest.new(url, :connect_timeout => 10, :inactivity_timeout => 20).get, 一句话,完成了http请求,并将请求的结果对象赋值给http.
  2. 上面的例子还通过fiber进行了并行调用.
    Fiber.new 创建纤程
    f = Fiber.current 获取当前纤程
    http.callback { f.resume(http) } 定义callback回调,
    http.errback { f.resume(http) } 定义errback回调
    Fiber.yield 挂起当前纤程,并交出控制权

详细了解纤程的信息可以, 移驾Fiber

基本上通过上面介绍的这种简单的方式,就可以构建起基本的域名监控系统了。

附带一提, 对于数据库操作,使用ruby的sequel,一个使用简单,功能强大的数据库组件。
例如:

等于

看起来很清晰明了, 又避免写复杂的sql.
感兴趣的朋友可以去sequel看看

遇到的问题:
1. redirect失效问题:

  • 由于我们的服务对外并非一个IP,同时还存在基于地域、运营商的DNS调度(后续可详见即将发表的SMARTDNS一文),那么我们的实现方式是,client先通过本地配置的DNS获取域名对应的IP列表,在通过设置header的方式进行http请求。
  • 问题来了,在使用过程中,发现redirect的配置会失效,一直获取不到最终页面。追踪每次请求的返回,发现HEADER中的HOST字段,在redirect之后,仍然为指定的:head => {'Host' => host},导致redirect失效,访问仍会落在Host对应的virtualserver上。

知道结症所在,我们下面来通过一行简单的代码来修复这个问题:

找到em-http-request中的client.rb文件,添加如下内容至unbind方法:

修改后的代码:

5 Comments

  1. 2013/07/26 at 10:28 上午

    ruby的一些库 还是相当好用的,赞

  2. wilbur
    2013/07/26 at 4:27 下午

    石总,不容易啊~~~ T_T

  3. shaosen fang
    2013/07/28 at 4:20 下午

    学习了

  4. crazyjin
    2013/10/29 at 2:13 上午

    我发现用em-http-request的keepalive 和 pipeline时如果遇到重定向,程序的反应会很慢。或许你知道原因。

    • shiyan
      2013/10/29 at 10:42 上午

      现在我还没有用到keepalive之类的, 如果方便,可以给我发个你的代码片段,我trace一下.

shaosen fang 进行回复 取消回复