rufus-scheduler在分离模式下在Rails + Unicorn上运行时不调度

时间:2015-01-29 00:01:42

标签: ruby-on-rails-4 unicorn rufus-scheduler

我正在使用rufus-scheduler在我的Ruby on Rails应用程序中安排一些工作。相关规格:

  • Ruby:2.1.2p95
  • Rails:4.1.1
  • Rufus-Scheduler:3.0.9

当我使用" rails s unicorn"运行应用程序时,调度程序运行得非常好。但是,当我使用" -d"分离服务器时选项,预定作业永远不会运行。

这是我的config / initializers / task_scheduler.rb文件:

require 'rubygems'
require 'rufus/scheduler'
require 'rake'

load File.join(Rails.root, 'lib', 'tasks', 'send_emails.rake')
MyApplication::Application.load_tasks
scheduler = Rufus::Scheduler.new(:lockfile => ".rufus-scheduler.lock")

if (!MyApplication.rake?)
  unless scheduler.down?

    Rails.logger.info "OK"

    scheduler.interval("1m") do
      Rails.logger.info "yup"
      system ("rake send_emails:mail_users")
    end 

  end
end

和我的unicorn.rb文件:

worker_processes 2
preload_app true
timeout 30

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

"!MyApplication.rake?" line是为了防止rake任务也运行调度程序;我已将此行添加到我的Rakefile中:

MyApplication.rake = true

当我查看我的日志时,我注意到" OK"正在打印行,所以我认为调度程序正在初始化,但是从不打印作业的记录器行并且rake任务不会运行。

此时我不确定问题出在我的独角兽配置还是我的调度程序配置中。任何帮助将不胜感激!

编辑1:

记录" rails s"

的输出
I, [2015-01-28T20:11:05.179505 #79141]  INFO -- : listening on addr=0.0.0.0:3000 fd=12
Before
Before
I, [2015-01-28T20:11:05.426386 #79141]  INFO -- : master process ready
After
After
I, [2015-01-28T20:11:05.434392 #79143]  INFO -- : worker=0 ready
I, [2015-01-28T20:11:05.435585 #79144]  INFO -- : worker=1 ready
yup

记录" rails s -d"

的输出
OK
Before
Before
After
After

正如jmettraux建议的那样,使用" -d"时,调度程序似乎在fork之后丢失了。选项。我把调度程序移到了一个类中,并从after_fork块中调用了初始化程序:

LIB / scheduler.rb

require 'rufus/scheduler'
class Scheduler

  def self.startup
    Rails.logger.info "startup"
    load File.join(Rails.root, 'lib', 'tasks', 'send_emails.rake')
    USA::Application.load_tasks
    scheduler = Rufus::Scheduler.new(:lockfile => ".rufus-scheduler.lock")

    if (!USA.rake?)
      Rails.logger.info "nope"
      unless scheduler.down?
        Rails.logger.info "OK"

        scheduler.interval("1m") do
          Rails.logger.info "yup"
          system ("rake send_emails:mail_users")
        end

        scheduler.join

      end
    end
  end

end

unicorn.rb:

worker_processes 2
preload_app true
timeout 100

load File.join(Rails.root, 'lib', 'scheduler.rb')

...

after_fork do |server, worker|
  Rails.logger.info "After"
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection

  Scheduler::startup

end

但是,当启动" rails s -d"时,这会失去控制。并且工人们不断被催生和杀害:

Before
Before
After
After
startup
startup
Before
After
Before
startup
After
startup
Before
After
startup

我确定我从after_fork块启动调度程序的实现可能是罪魁祸首,但我不确定是什么导致了这一点。

编辑2

我是愚蠢的。我正在使用jmettraux链接的gist,但是当我试图让它在我的应用程序中工作时,我将其剔除了。我回去从头开始启动unicorn.rb和scheduler.rb,它现在正在工作!

1 个答案:

答案 0 :(得分:2)

你应该在after_fork块中添加一些Rails.logger.info(" XXX")以查看它是在OK之前还是之后发生。

似乎有人遇到了同样的问题并提出了一些建议:https://gist.github.com/jkraemer/3851917 它已经四岁了,但它可以给你一些启发。

"要点"它似乎是在after_fork块中运行/启动rufus-scheduler(这样它的线程就不会在fork中被杀死)。