Задержка перезапуска рабочих мест + лучшие практики Capistrano - PullRequest
13 голосов
/ 14 марта 2012

Я просто хотел понять лучшие практики для перезапуска работников с задержкой на работу с использованием capistrano. У меня есть кучка рабочих, которые обрабатывают длинные работы (до 10 минут).

Я столкнулся с двумя сценариями во время развертывания, пока рабочие обрабатывают-

1)

Я прекращаю работу с отложенными заданиями перед развертыванием: перезапускаю задачу и снова запускаю их после развертывания: перезапускаю задачу.

Но в этом сценарии мое приложение не будет перезапущено до тех пор, пока отложенные задания не будут завершены (это может быть нормально - но сценарий cap deploy буквально находится там, пока задание не выполнено, и он может остановить всех работников), прежде чем продолжить с задача перезапуска приложения.

2) Я также попытался остановить / запустить работников delayedjobs после задачи перезапуска - но это вызвало всевозможные драмы, в результате которых задачи были остановлены без ожидания, но в таблице delayedjobs они были перечислены и назначены работнику с PID, который не существует!

Есть еще варианты? Или я вынужден ждать, как указано в сценарии 1.

Большое спасибо.

Редактировать: Я только что понял со сценарием 1 .. это не ждет! Задание на остановку принудительно убьет моего работника, даже если оно еще не закончено!

 ** [out] delayed_job: trying to stop process with pid 9630...
 ** [out] delayed_job: process with pid 9630 won't stop, we forcefully kill it...
 ** [out] 
 ** [out] delayed_job: process with pid 9630 successfully stopped.

Ответы [ 6 ]

1 голос
/ 18 апреля 2015

На самом деле не уверен, что мое решение достаточно хорошее.Но в любом случае у него есть шанс жить.Просто создайте задачу Rake и запустите ее в процессе развертывания:

  desc 'Wait for delayed job completion'
  task wait_for_complete_background_jobs: :environment do
    loop do
      exit unless Delayed::Job.where(locked_at: nil).exists?
      sleep 2
    end
  end

Задача Rake ожидает заблокированные задания и завершает работу сразу после того, как список заблокированных задач пуст.Вот как я представляю его использование (обратите внимание, важна последовательность операций):

  1. Остановка веб-сервера
  2. Запуск задачи rake
  3. Остановка отложенного задания
  4. Обновление кода
  5. Запуск отложенного задания
  6. Запуск веб-сервера
1 голос
/ 14 февраля 2013

Если ваши изменения развертывания изменяют схему базы данных, вы вынуждены ждать.

Если это не так, вы можете установить флаг, который рабочие проверяют в конце каждой работы. При развертывании вы устанавливаете флаг, и после того, как долго работающий работник заканчивает работу, он заменяет себя, выполняя нового работника. Таким образом, вы никогда не запускаете и не останавливаете работников - они просто работают и загружают последний код при запуске следующего задания.

0 голосов
/ 29 апреля 2013

Я бы порекомендовал вам проверять всякий раз, когда - вероятно, лучший драгоценный камень для управления отложенными заданиями. Я пробовал разные решения, начиная со старого забытого cron + wget, но всякий раз, когда это дает лучший контроль над этим. И это прекрасно сочетается с Capistrano. НТН

0 голосов
/ 18 февраля 2013

Хороший вопрос - я пробовал много разных вещей, но моя стратегия состоит в том, чтобы все было просто.

  1. Не используйте God или Monit или что-либо, что запускается от имени root, требуя, чтобы тот же пользователь, который запускает ваше приложение, имел права sudo для его перезапуска. Учитывая недавние события в области безопасности rails, последнее, что вам нужно, это то, чтобы у пользователя вашего приложения была хорошая возможность получить root.
  2. Вместо этого используйте задачу rake или thor для запуска / остановки / перезапуска задач.
  3. Используйте nohup, чтобы демонизировать процесс.

Вот некоторые очень простые задачи, которые могут управлять простыми фоновыми задачами с помощью resque, например:

class Resque < Thor

  desc "start", "Starts resque workers"
  def start
    system('(PIDFILE=/tmp/resque-myapp.pid nohup rake resque:work QUEUES="*" &) &')
  end

  desc "stop", "Stops resque workers"
  def stop
    pidfile = '/tmp/resque-myapp.pid'
    if File.exist?(pidfile)
      pid = File.open(pidfile).first.to_i
      puts "Killing process #{pid}..."
      system("kill -QUIT #{pid}")
      File.delete(pidfile)
      sleep(5)
    else
      puts "No resque pidfile found"
    end
  end
end

Тогда в вашем deploy.rb файле:

after 'deploy',         "resque:restart"

namespace :resque do
  task :restart do
    puts "Stopping resque workers.."
    run("cd #{current_path} && thor resque:stop", :options => { :pty => true })
    puts "Starting resque workers.."
    run("cd #{current_path} && thor resque:start > /dev/null 2>&1 &", :options => { :pty => true })
  end
end

Эта стратегия может работать даже с RVM, если это интересно. Вам нужно что-то подобное перед командой перезагрузки, в дополнение к обычным rvm-capistrano задачам:

after  'deploy:setup', 'thor:install'
namespace :thor do
  task :install do
    puts "Installing thor..."
    run_locally('cap rvm:install_gem GEM=thor')
  end
end

after "deploy",         "rvm:trust_rvmrc"
namespace :rvm do
  task :trust_rvmrc do
    run "rvm rvmrc trust #{release_path}"
  end
end

И, наконец, что не менее важно, с помощью RVM лучше поместить в ~/.bashrc то, что установщик обычно разделяет между этим файлом и .bash_profile, и убедитесь, что режим файла - 0400, чтобы он не перекрывался программа установки RVM:

PATH=$HOME/.rvm/bin:/usr/local/bin/:$PATH # Add RVM to PATH for scripting
export PATH
export RAILS_ENV=production
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
0 голосов
/ 18 февраля 2013

Я закончил тем, что переместил свои "долго работающие процессы" в собственный скрипт на Ruby, используя гем daemons. Спасибо за совет, ребята!

0 голосов
/ 14 марта 2012

Вы можете исправить второй сценарий, чтобы поместить файл pid в общий каталог, чтобы он не исчезал. Второй сценарий может сработать, и если у вас нет миграции, он может конфликтовать с отложенной работой.

...