【问题标题】:Sidekiq fails to stop under runitSidekiq 无法在 runit 下停止
【发布时间】:2014-02-27 06:23:33
【问题描述】:

我们在 runit 下运行了许多服务,效果非常好。

最近开始使用 Sidekiq,非常棒。它在 runit 下运行它。问题是在运行“sv stop”时。它并没有停止这个过程。调用 restart 实际上会启动另一个 sidekiq 实例,让旧实例继续运行。

这是我们的示例运行文件:

#!/bin/sh
cd /PATH_TO_SIDEKIQ
exec 2>&1
export DB_POOL_SIZE=25
exec bundle exec sidekiq -e production 2>&1 | logger -p local2.info -t sidekiq

supervise/pid 中的 pid 文件与正在运行的 pid 匹配。

谢谢,杰里米

【问题讨论】:

    标签: sidekiq runit


    【解决方案1】:

    好的,我不确定确切的原因,但我认为这就是 SideKiq 的启动方式。它得到了它自己的 pid,并且 runit 也分配了一个。无论如何,我已经通过修改内置的 capistrano 配方解决了这个问题。

    基本思想是使用 sidekiqctl 发送 :quite 信号,以便工人停止接受新工作。然后在 :stop 我们停止 runit 然后发送 sidekiqctl :stop 信号。启动时,我们使用 runit 再次启动进程。

    Capistrano::Configuration.instance.load do
    
      _cset(:sidekiq_default_hooks) { true }
      _cset(:sidekiq_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiq" }
      _cset(:sidekiqctl_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiqctl" }
      _cset(:sidekiq_timeout)   { 10 }
      _cset(:sidekiq_role)      { :app }
      _cset(:sidekiq_pid)       { "#{current_path}/tmp/pids/sidekiq.pid" }
      _cset(:sidekiq_processes) { 1 }
    
      if fetch(:sidekiq_default_hooks)
        before "deploy:update_code", "sidekiq:quiet"
        after "deploy:stop",    "sidekiq:stop"
        after "deploy:start",   "sidekiq:start"
        before "deploy:restart", "sidekiq:restart"
      end
    
      namespace :sidekiq do
        def for_each_process(&block)
          fetch(:sidekiq_processes).times do |idx|
            yield((idx == 0 ? "#{fetch(:sidekiq_pid)}" : "#{fetch(:sidekiq_pid)}-#{idx}"), idx)
          end
        end
    
        desc "Quiet sidekiq (stop accepting new work)"
        task :quiet, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
          for_each_process do |pid_file, idx|
            run "if [ -d #{current_path} ] && [ -f #{pid_file} ] && kill -0 `cat #{pid_file}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} quiet #{pid_file} ; else echo 'Sidekiq is not running'; fi"
          end
        end
    
        desc "Stop sidekiq"
        task :stop, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
          for_each_process do |pid_file, idx|
            sidekiq_dir = idx == 0 ? "/SERVICE_DIR/sidekiq" : "/SERVICE_DIR/sidekiq-#{idx}"
            run "sv stop #{sidekiq_dir}"
            run "if [ -d #{current_path} ] && [ -f #{pid_file} ] && kill -0 `cat #{pid_file}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} stop #{pid_file} #{fetch :sidekiq_timeout} ; else echo 'Sidekiq is not running'; fi"
          end
        end
    
        desc "Start sidekiq"
        task :start, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
          rails_env = fetch(:rails_env, "production")
          for_each_process do |pid_file, idx|
            sidekiq_dir = idx == 0 ? "/SERVICE_DIR/sidekiq" : "/SERVICE_DIR/sidekiq-#{idx}"
            run "sv start #{sidekiq_dir}"
          end
        end
    
        desc "Restart sidekiq"
        task :restart, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
          stop
          start
        end
    
      end
    end
    

    【讨论】:

      【解决方案2】:

      我对 Capistrano 3 的解决方案:

      set :sidekiq_runit_service_name, "sidekiq"
      set :sidekiq_default_hooks, ->{ true }
      set :sidekiq_cmd, ->{ "#{fetch(:bundle_cmd, "bundle")} exec sidekiq" }
      set :sidekiqctl_cmd, ->{ "#{fetch(:bundle_cmd, "bundle")} exec sidekiqctl" }
      set :sidekiq_timeout, ->{ 10 }
      set :sidekiq_role,    ->{ :app }
      set :sidekiq_pid,     ->{ "#{current_path}/tmp/pids/sidekiq.pid" }
      
      namespace :sidekiq do
      
        desc "Quiet sidekiq (stop accepting new work)"
        task :quiet do
          on roles(fetch(:sidekiq_role)) do
            execute "if [ -d #{current_path} ] && [ -f #{fetch(:sidekiq_pid)} ] && kill -0 `cat #{fetch(:sidekiq_pid)}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} quiet #{fetch(:sidekiq_pid)} ; else echo 'Sidekiq is not running'; fi"
          end
        end
      
        desc "Stop sidekiq"
        task :stop do
          on roles(fetch(:sidekiq_role)) do
            execute "sv stop #{fetch(:sidekiq_runit_service_name)}; true"
            execute "if [ -d #{current_path} ] && [ -f #{fetch(:sidekiq_pid)} ] && kill -0 `cat #{fetch(:sidekiq_pid)}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} stop #{fetch(:sidekiq_pid)} #{fetch :sidekiq_timeout} ; else echo 'Sidekiq is not running'; fi"
          end
        end
      
        desc "Start sidekiq"
        task :start do
          on roles(fetch(:sidekiq_role)) do
            execute "sv start #{fetch(:sidekiq_runit_service_name)}"
          end
        end
      
        desc "Restart sidekiq"
        task :restart do
          invoke 'sidekiq:stop'
          invoke 'sidekiq:start'
        end
      
      end
      
      if fetch(:sidekiq_default_hooks)
        before 'deploy:started',   "sidekiq:quiet"
        after  'deploy:updated',   "sidekiq:stop"
        after  'deploy:reverted',  "sidekiq:stop"
        after  'deploy:published', "sidekiq:start"
        after  'deploy:restart',   "sidekiq:restart"
      end
      

      【讨论】:

        猜你喜欢
        • 2020-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多