rufus-scheduler 在分离模式下 运行 在 Rails+Unicorn 之上时不进行调度
rufus-scheduler not scheduling when running on top of Rails+Unicorn in detached mode
我正在使用 rufus-scheduler 在我 Ruby 的 Rails 应用程序中安排一些工作。相关规格:
- Ruby: 2.1.2p95
- Rails: 4.1.1
- Rufus-调度程序: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 任务也从 运行ning 调度程序;我已将此行添加到我的 Rakefile 中:
MyApplication.rake = true
当我查看我的日志时,我注意到正在打印 "OK" 行,所以我相信调度程序正在正确初始化,但是作业的记录器行从未打印过,rake 任务也没有打印t 运行.
此时我不确定问题出在我的独角兽配置上,还是我的调度程序配置上。任何帮助将不胜感激!
编辑 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”选项时,调度程序似乎在分叉后丢失了。我稍微调整了一下,将调度程序移到了 class 中,并从 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" 并且 worker 不断地被生成和杀死:
Before
Before
After
After
startup
startup
Before
After
Before
startup
After
startup
Before
After
startup
我确定我从 after_fork 块启动调度程序的实现可能是罪魁祸首,但我不确定到底是什么原因造成的。
编辑 2
我傻了。我正在使用 jmettraux 链接的 gist,但是当我试图让它在我的应用程序中工作时,我把它搞砸了。我回去从头开始我的 unicorn.rb 和 scheduler.rb,它现在可以工作了!
您应该在 after_fork 块中添加一些 Rails.logger.info("XXX") 以查看它是发生在 OK 之前还是之后。
似乎有人遇到了同样的问题并提出了一些建议:https://gist.github.com/jkraemer/3851917
已经四岁了,但它可以给你一些灵感。
它的 "gist" 似乎是 run/start rufus-scheduler 在 after_fork 块中(这样它的线程就不会在 fork 中被杀死)。
我正在使用 rufus-scheduler 在我 Ruby 的 Rails 应用程序中安排一些工作。相关规格:
- Ruby: 2.1.2p95
- Rails: 4.1.1
- Rufus-调度程序: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 任务也从 运行ning 调度程序;我已将此行添加到我的 Rakefile 中:
MyApplication.rake = true
当我查看我的日志时,我注意到正在打印 "OK" 行,所以我相信调度程序正在正确初始化,但是作业的记录器行从未打印过,rake 任务也没有打印t 运行.
此时我不确定问题出在我的独角兽配置上,还是我的调度程序配置上。任何帮助将不胜感激!
编辑 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”选项时,调度程序似乎在分叉后丢失了。我稍微调整了一下,将调度程序移到了 class 中,并从 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" 并且 worker 不断地被生成和杀死:
Before
Before
After
After
startup
startup
Before
After
Before
startup
After
startup
Before
After
startup
我确定我从 after_fork 块启动调度程序的实现可能是罪魁祸首,但我不确定到底是什么原因造成的。
编辑 2
我傻了。我正在使用 jmettraux 链接的 gist,但是当我试图让它在我的应用程序中工作时,我把它搞砸了。我回去从头开始我的 unicorn.rb 和 scheduler.rb,它现在可以工作了!
您应该在 after_fork 块中添加一些 Rails.logger.info("XXX") 以查看它是发生在 OK 之前还是之后。
似乎有人遇到了同样的问题并提出了一些建议:https://gist.github.com/jkraemer/3851917 已经四岁了,但它可以给你一些灵感。
它的 "gist" 似乎是 run/start rufus-scheduler 在 after_fork 块中(这样它的线程就不会在 fork 中被杀死)。