在后台运行resque

时间:2011-11-13 19:31:05

标签: ruby-on-rails ruby-on-rails-3 background daemon resque

我有一个带有resque队列系统的工作轨道应用程序,它运行良好。但是,我没有一个很好的方法来真正妖魔化resque工人。

我可以通过rake resque来启动它们:work QUEUE =“*”但我想这不是你应该让你的工作人员在前台运行的重点。出于某种原因,没有人似乎在解决这个问题。在官方resque github页面上声明你可以做这样的事情:

PIDFILE=./resque.pid BACKGROUND=yes QUEUE="*" rake resque:work
好吧 - 它至少没有在这里进入背景。

8 个答案:

答案 0 :(得分:15)

resque-pool的+1 - 它真的很震撼。我们将它与上帝结合使用,以确保它始终可用。

# Resque
God.watch do |w|

  w.dir = RAILS_ROOT

  w.name = "resque-pool"
  w.interval = 30.seconds
  w.start = "cd #{RAILS_ROOT} && sudo -u www-data sh -c 'umask 002 && resque-pool -d -E #{RAILS_ENV}'"
  w.start_grace = 20.seconds
  w.pid_file = "#{RAILS_ROOT}/tmp/pids/resque-pool.pid"

  w.behavior(:clean_pid_file)

  # restart if memory gets too high
  #w.transition(:up, :restart) do |on|
  #  on.condition(:memory_usage) do |c|
  #    c.above = 350.megabytes
  #    c.times = 2
  #  end
  #end

  # determine the state on startup
  w.transition(:init, { true => :up, false => :start }) do |on|
    on.condition(:process_running) do |c|
      c.running = true
    end
  end

  # determine when process has finished starting
  w.transition([:start, :restart], :up) do |on|
    on.condition(:process_running) do |c|
      c.running = true
      c.interval = 5.seconds
    end

    # failsafe
    on.condition(:tries) do |c|
      c.times = 5
      c.transition = :start
      c.interval = 5.seconds
    end
  end

  # start if process is not running
  w.transition(:up, :start) do |on|
    on.condition(:process_running) do |c|
      c.running = false
    end
  end
end

这为您提供了一种非常优雅的方式来在您的工作人员中重新加载代码而不会中断作业 - 在部署时只需kill -2您的resque-pool。空闲的工人会立即死亡,繁忙的工人将在他们完成目前的工作后死亡,而且上帝将使用你的新代码重新启动resque-pool。

这些是Capistrano的Resque任务:

namespace :resque do

  desc "Starts resque-pool daemon."
  task :start, :roles => :app, :only => { :jobs => true } do
    run "cd #{current_path};resque_pool -d -e #{rails_env} start"
  end

  desc "Sends INT to resque-pool daemon to close master, letting workers finish their jobs."
  task :stop, :roles => :app, :only => { :jobs => true } do
    pid = "#{current_path}/tmp/pids/resque-pool.pid"
    sudo "kill -2 `cat #{pid}`"
  end

  desc "Restart resque workers - actually uses resque.stop and lets God restart in due course."
  task :restart, :roles => :app, :only => { :jobs => true } do
    stop # let God restart.
  end

  desc "List all resque processes."
  task :ps, :roles => :app, :only => { :jobs => true } do
    run 'ps -ef f | grep -E "[r]esque-(pool|[0-9])"'
  end

  desc "List all resque pool processes."
  task :psm, :roles => :app, :only => { :jobs => true } do
    run 'ps -ef f | grep -E "[r]esque-pool"'
  end

end

当resque-pool分支工作人员时,您可能需要重新连接任何数据库连接 - 检查文档。

答案 1 :(得分:13)

我遇到了同样的问题,以下内容适用于我。

PIDFILE=./resque.pid BACKGROUND=yes QUEUE="*" rake resque:work >>  worker1.log &

您还可以将STDERR重定向到同一个日志文件。

答案 2 :(得分:5)

要妖怪化一个过程,您可以使用nohup

nohup cmd &

在resque的github上有一个monit的配置,它显示了如何使用nohup,它看起来像这样:

nohup bundle exec rake resque:work QUEUE=queue_name PIDFILE=tmp/pids/resque_worker_QUEUE.pid & >> log/resque_worker_QUEUE.log 2>&1

答案 3 :(得分:4)

您应该考虑的另一个选择是使用resque pool gem来管理您的员工。

您可以使用以下命令在后台运行resque pool:

  

resque-pool --daemon - environment production

答案 4 :(得分:2)

BACKGROUND环境变量添加到Resque 1.20;确保你没有使用1.19或更低版本。

答案 5 :(得分:1)

一种好方法是使用God进行管理。它启动了Resque的守护程序版本并对其进行监控。实际上,你可以选择使用Resque作为守护进程并让神使用Resque作为守护进程。我选择选项2。

resque.god文件示例:

rails_env   = ENV['RAILS_ENV']  || "production"
rails_root  = ENV['RAILS_ROOT'] || "/path/to/my/app/current"
num_workers = rails_env == 'production' ? 5 : 2

num_workers.times do |num|
  God.watch do |w|
    w.dir      = "#{rails_root}"
    w.name     = "resque-#{num}"
    w.group    = 'resque'
    w.interval = 30.seconds
    w.env      = {"QUEUE"=>"critical,mailer,high,low", "RAILS_ENV"=>rails_env}
    w.start    = "bundle exec rake -f #{rails_root}/Rakefile resque:work"
    w.stop_signal = 'QUIT'
    w.stop_timeout = 20.seconds

    w.uid = 'myappuser'
    w.gid = 'myappuser'

    w.behavior(:clean_pid_file)

    # restart if memory gets too high
    w.transition(:up, :restart) do |on|
      on.condition(:memory_usage) do |c|
        c.above = 350.megabytes
        c.times = 2
        c.notify = {:contacts => ['maxime'], :priority => 9, :category => 'myapp'}
      end
    end

    # determine the state on startup
    w.transition(:init, { true => :up, false => :start }) do |on|
      on.condition(:process_running) do |c|
        c.running = true
      end
    end

    # determine when process has finished starting
    w.transition([:start, :restart], :up) do |on|
      on.condition(:process_running) do |c|
        c.running = true
        c.interval = 5.seconds
      end

      # failsafe
      on.condition(:tries) do |c|
        c.times = 5
        c.transition = :start
        c.interval = 5.seconds
      end
    end

    # start if process is not running
    w.transition(:up, :start) do |on|
      on.condition(:process_running) do |c|
        c.running = false
        c.notify = {:contacts => ['maxime'], :priority => 1, :category => 'myapp'}
      end
    end
  end
end

答案 6 :(得分:1)

我也遇到过这个问题,我开始工作,但我遇到了问题

  • 背景导致工作人员始终处于启动模式。
  • nohup进程在完成后立即被杀死,我们必须等待几秒钟。但是在'&'
  • 之后无法附加更多命令

最后,我必须创建一个shell,让它在nohup后5s睡觉...打电话。 我的代码

desc 'Start resque'
task :start, :roles => :app do
  run("cd #{current_path} ; echo \"nohup bundle exec rake resque:work QUEUE=* RAILS_ENV=#{rails_env} PIDFILE=tmp/pids/resque_worker_1.pid &\nnohup bundle exec rake resque:work QUEUE=* RAILS_ENV=#{rails_env} PIDFILE=tmp/pids/resque_worker_2.pid &\nsleep 5s\" > startworker.sh ")
  run("cd #{current_path} ; chmod +x startworker.sh")
  run("cd #{current_path} ; ./startworker.sh")
  run("cd #{current_path} ; rm startworker.sh")
end

我知道这是一种情况解决方案。但它在我的项目中运作良好

答案 7 :(得分:0)

您可以使用this脚本管理您的员工。可用命令:

rake resque:start_workers
rake resque:stop_workers
rake resque:restart_workers

还包括resque-scheduler。注释这一行以禁用它:

pid = spawn(env_vars, 'bundle exec rake resque:scheduler', ops_s)
Process.detach(pid)