2009-09-17 1 views
1

Ситуация:Работы с Старлинг и нескольких экземплярами Барбоса через Mongrel кластер

  • В типичной установке кластера, у меня есть 5 экземпляров беспородных отстают Apache 2.
  • В одном из моего инициализатор файлов, Я планирую задачу cron с помощью Rufus::Scheduler, которая в основном отправляет пару писем.

Проблема:

  • Задание выполняется 5 раз, один раз для каждого экземпляра беспородного и каждый получатель заканчивает получать 5 писем (несмотря на то, я хранить журналы каждой отправленной почты и проверить журнал перед отправкой). Возможно ли, что, поскольку все 5 экземпляров запускают задачу в одно и то же время, они заканчивают чтение журналов электронной почты до, они написаны?

Я ищу решение, которое позволит выполнять задачи только один раз. У меня также есть демон Starling, который можно использовать.

ответ

-1

Почему вы не используете mod_passenger (phusion)? Я перешел от mongrel к phusion, и он работал идеально (с указанием времени < 5 минут)!

+1

Я боюсь, что это невозможно. – Swanand

+0

Возможно, вы хотите использовать другой (возможно, лучший) плагин? http://ruby-toolbox.com/categories/queueing.html – Lichtamberg

+0

Помогло ли вам это? – Lichtamberg

3

Плагин для рельсов специально решает вашу проблему. Он использует rufus-scheduler и обеспечивает загрузку среды только один раз.

+1

Выглядит интересно, +1 от меня. Я сейчас использую пустой файл как объект Mutex и использую его в режиме эксклюзивной блокировки, чтобы избежать многократной загрузки. – Swanand

1

так, как я делаю это прямо сейчас:

  1. Попробуйте открыть файл в эксклюзивном режиме блокировки
  2. Когда замок приобретается, проверьте наличие сообщений в Старлинг
  3. Если сообщение существует, другой процесс уже запланировано задание
  4. Установите сообщение еще раз в очередь и выйдите.
  5. Если сообщение не найдено, планировать работу, установить сообщение и выход

Вот код, который делает это:

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") 
Смежные вопросы