使用god监视unicorn

2013年9月17日 19:27

最近使用nginx+unicorn+sinatra的api服务器要上线了,首选的是易于配置、扩展的gem,god

  • Config file is written in Ruby
  • Easily write your own custom conditions in Ruby
  • Supports both poll and event based conditions
  • Different poll conditions can have different intervals
  • Integrated notification system (write your own too!)
  • Easily control non-daemonizing scripts

简单配置

loop do
  puts 'Hello'
  sleep 1
end

 

God.watch do |w|
  w.name = "unicorn"
  w.start = "ruby /full/path/to/app.rb"
  w.keepalive
end

clockwork使用

2013年9月24日 21:15

在定时或者周期执行任务时,crontab是常用的工具,但是很多时候,crontab不是最好的选择。clockwork是ruby中替代crontab的一个gem。

在include Clockwork模块后,可以很直观,方便的管理任务,可以精确到秒的执行任务。

require 'clockwork'
include Clockwork

handler do |job|
  puts "Running #{job}"
end

every(10.seconds, 'frequent.job')
every(3.minutes, 'less.frequent.job')
every(1.hour, 'hourly.job')

every(1.day, 'midnight.job', :at => '00:00')

使用clockwork的一大好处是可以用ruby进行管理,复用redis连接,环境初始化等

 

 

MQTT简介

2013年9月24日 21:16

mqtt是IBM开发的一个轻量级发布/订阅消息协议。可用于受限环境,有多种语言的实现。协议的特点有:

  • 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
  • 对负载内容屏蔽的消息传输。 使用 TCP/IP 提供网络连接。
  • 有三种消息发布服务质量:
    1. 至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
    2. 至少一次”,确保消息到达,但消息重复可能会发生。
    3. 只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
  • 使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。
  •  

实际使用中的一些须知:

QoS

MQTT 的QoS决定broker如何确保消息达到客户端. QoS是双向的,客户端可以以任意QoS发布消息,以任意QoS订阅主题. 例如,客户端A以QoS 2发布消息,客户端B以QoS 0订阅,那么消息将以QoS 0送达B,如果另一个客户端C,以QoS 2订阅这个主题,那么消息将以QoS 2送达客户端C。 如果客户端以QoS 2订阅,消息以QoS 0发布,那么消息将以QoS 0送达客户端。

 

ruby搭配redis使用

2013年9月11日 19:51

设计的客户端管理和任务分发系统使用redis存储,使用名字空间的方式进行管理

对每一个用户,分配一个id,设计键值

account:id:username
account:id:province
account:id:city
account:id:isp

...

一开始直接使用reids-rb进行操作,redis.get("account:#{id}:username")

后来发现一个操作redis的gem--Ohm,体验了ohm,内部也是这样的键值进行存储的,但是Ohm封装的很好,达到了类似activerecord的效果,不过由于系统需要和其他语言进行交互,如果用Ohm会不大方便。于是找到作者的另一个gem--nest,通过nest可以直接复用原来的设计,方便的操作。

account = Nest.new("account",redis)
account[id][:username].getNest

源码如下,非常简洁。

require "redis"

class Nest < String
  METHODS = [:append, :bitcount, :blpop, :brpop, :brpoplpush, :decr,
  :decrby, :del, :dump, :exists, :expire, :expireat, :get, :getbit,
  :getrange, :getset, :hdel, :hexists, :hget, :hgetall, :hincrby,
  :hincrbyfloat, :hkeys, :hlen, :hmget, :hmset, :hset, :hsetnx, :hvals,
  :incr, :incrby, :incrbyfloat, :lindex, :linsert, :llen, :lpop,
  :lpush, :lpushx, :lrange, :lrem, :lset, :ltrim, :move, :persist,
  :pexpire, :pexpireat, :psetex, :pttl, :publish, :rename, :renamenx,
  :restore, :rpop, :rpoplpush, :rpush, :rpushx, :sadd, :scard,
  :sdiff, :sdiffstore, :set, :setbit, :setex, :setnx, :setrange,
  :sinter, :sinterstore, :sismember, :smembers, :smove, :sort, :spop,
  :srandmember, :srem, :strlen, :subscribe, :sunion, :sunionstore,
  :ttl, :type, :unsubscribe, :watch, :zadd, :zcard, :zcount,
  :zincrby, :zinterstore, :zrange, :zrangebyscore, :zrank, :zrem,
  :zremrangebyrank, :zremrangebyscore, :zrevrange, :zrevrangebyscore,
  :zrevrank, :zscore, :zunionstore]

  attr :redis

  def initialize(key, redis = Redis.current)
    super(key.to_s)
    @redis = redis
  end

  def [](key)
    self.class.new("#{self}:#{key}", redis)
  end

  METHODS.each do |meth|
    define_method(meth) do |*args, &block|
      redis.send(meth, self, *args, &block)
    end
  end
end

Nest继承String类,使用dynamic methods动态定义方法对redis的操作进行封装,初看很简单,但是细细琢磨,有一些ruby中的细节需要熟悉。我们知道ruby每个方法的最后一行会成为返回值,那么initialize后,@redis是不是成为返回值了?答案是否,使用new实例化对象的时候,并不是简单的调用了initialize方法,new方法返回一个Nest对象。根据stackoverflow上的回答:

new is a class method, which generally creates an instance of the class (this deals with the tricky stuff like allocating memory that Ruby shields you from so you don't have to get too dirty).

Then, initialize, an instance method, tells the object to set its internal state up according to the parameters requested.

class Class
  def new(*args, &block)
    obj = allocate

    obj.initialize(*args, &block)
    # actually, this is obj.send(:initialize, …) because initialize is private

    obj
  end
end

Nest继承String,对象的值为字符串,作为redis的键值,Nest中的self就是键值,[]方法new新的Nest对象,形成键值的映射。通过send方法,将动态生成的Nest的实例方法派发到redis对象执行。

简单,优美的Ruby元编程。

技术blog

2013年9月11日 09:46

技术博客,记录互联网学习,关键字:debian,centos,nginx,apache,reids,memcache,git,ruby,sinatra,rails,mqtt