【问题标题】:Run resque in background在后台运行resque
【发布时间】:2011-12-28 04:22:19
【问题描述】:

我有一个运行良好的带有 resque 队列系统的 rails 应用程序。但是,我缺乏真正妖魔化 resque 工人的好方法。

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

PIDFILE=./resque.pid BACKGROUND=yes QUEUE="*" rake resque:work

嗯 - 它至少不会在这里分叉到后台。

【问题讨论】:

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


    【解决方案1】:

    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(s)。空闲的工人会立即死亡,忙碌的工人会在他们完成当前工作后死亡,上帝会使用你的新代码重新启动 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 分叉工作人员时,您可能需要重新连接任何数据库连接 - 请查看文档。

    【讨论】:

    • 截至 2013-2014 年末,此设置的任何要点或更新?任何地方的例子?
    • 得到这个:`resque:stop' 只为匹配 {:roles=>:app, :only=>{:jobs=>true}} 的服务器运行,但没有匹配的服务器有任何建议吗?
    【解决方案2】:

    我遇到了同样的问题,以下对我有用。

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

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

    【讨论】:

      【解决方案3】:

      要妖魔化进程,您可以使用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
      

      【讨论】:

      • 你能否详细解释一下这个 cmd 的作用。我在日志文件中看不到任何输出,而是在 nohup.out 文件中看到 o/p。
      【解决方案4】:

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

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

      resque-pool --daemon --environment production

      【讨论】:

        【解决方案5】:

        BACKGROUND 环境变量已添加到 Resque 1.20;确保您使用的不是 1.19 或更低版本。

        【讨论】:

        • 我有 1.17 版本,而 BACKGROUND=yes 对我不起作用。谢谢!
        【解决方案6】:

        一个好方法是使用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
        

        【讨论】:

          【解决方案7】:

          我也遇到了这个问题,我在 cap 任务中开始工作,但是我遇到了问题

          • BACKGROUND 导致 worker 始终处于启动模式。
          • nohup 进程在完成后立即被杀死,我们必须等待几秒钟。但无法在 '&' 后追加更多命令

          最后,我必须创建一个 shell,让它在 nohup... 调用后休眠 5 秒。 我的代码

          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
          

          我知道这是一种情况解决方案。但它在我的项目中效果很好

          【讨论】:

            【解决方案8】:

            您可以使用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)
            

            【讨论】:

              猜你喜欢
              • 2014-04-18
              • 1970-01-01
              • 2013-01-10
              • 2019-07-31
              • 2016-05-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-06
              相关资源
              最近更新 更多