代码之家  ›  专栏  ›  技术社区  ›  Swanand

通过Mongrel集群使用Starling和多个Mongrel实例

  •  1
  • Swanand  · 技术社区  · 15 年前

    • 在典型的集群设置中,我有5个mongrel实例运行在apache2后面。
    • Rufus::Scheduler

    问题:

    • 这个任务运行5次,每个mongrel实例一次,每个接收者得到5封邮件(尽管我存储了每个发送邮件的日志并在发送前检查日志)。是否有可能因为所有5个实例都在同一时间运行任务,最终它们都会读取电子邮件日志 之前 他们写下来了?

    3 回复  |  直到 12 年前
        1
  •  3
  •   jaaronfarr    15 年前

    这个 rooster rails插件专门解决您的问题。它使用rufus调度程序并确保环境只加载一次。

        2
  •  1
  •   Swanand    15 年前

    1. 当获得锁时,检查Starling中的消息
    2. 如果消息存在,则说明其他进程已计划该作业
    3. 再次将消息设置为队列并退出。
    4. 如果找不到消息,请安排作业,设置消息并退出

    下面是实现这一点的代码:

        starling = MemCache.new("#{Settings[:starling][:host]}:#{Settings[:starling][:port]}")
        mutex_filename = "#{RAILS_ROOT}/config/file.lock"
        scheduler = Rufus::Scheduler.start_new
    
    
        # The filelock method, taken from Ruby Cookbook
        # This will ensure unblocking of the files
        def flock(file, mode)
          success = file.flock(mode)
          if success
            begin
              yield file
            ensure
              file.flock(File::LOCK_UN)
            end
          end
          return success
        end
    
        # open_lock method, taken from Ruby Cookbook
        # This will create and hold the locks
        def open_lock(filename, openmode = "r", lockmode = nil)
          if openmode == 'r' || openmode == 'rb'
            lockmode ||= File::LOCK_SH
          else
            lockmode ||= File::LOCK_EX
          end
          value = nil
          # Kernerl's open method, gives IO Object, in our case, a file
          open(filename, openmode) do |f|
            flock(f, lockmode) do
              begin
                value = yield f
              ensure
                f.flock(File::LOCK_UN) # Comment this line out on Windows.
              end
            end
            return value
          end
        end
    
        # The actual scheduler
        open_lock(mutex_filename, 'r+') do |f|
          puts f.read
          digest_schedule_message = starling.get("digest_scheduler")
          if digest_schedule_message
            puts "Found digest message in Starling. Releasing lock. '#{Time.now}'"
            puts "Message: #{digest_schedule_message.inspect}"
            # Read the message and set it back, so that other processes can read it too
            starling.set "digest_scheduler", digest_schedule_message
          else
            # Schedule job
            puts "Scheduling digest emails now. '#{Time.now}'"
            scheduler.cron("0 9 * * *") do
              puts "Begin sending digests..."
              WeeklyDigest.new.send_digest!
              puts "Done sending digests."
            end
            # Add message in queue
            puts "Done Scheduling. Sending the message to Starling. '#{Time.now}'"
            starling.set "digest_scheduler", :date => Date.today
          end
        end
    
        # Sleep will ensure all instances have gone thorugh their wait-acquire lock-schedule(or not) cycle
        # This will ensure that on next reboot, starling won't have any stale messages
        puts "Waiting to clear digest messages from Starling."
        sleep(20)
        puts "All digest messages cleared, proceeding with boot."
        starling.get("digest_scheduler")
    
        3
  •  -1
  •   BvuRVKyUVlViVIc7    15 年前

    你为什么不用摩登乘客号(phusion)?我从混血儿搬到了phusion,它工作得很好(时间长度是5分钟)!