Как заставить Bluepill перезапустить работников Resque только после достижения безопасного статуса
Допустим, это мой рабочий:
class FooWorker
@queue = :foo
def self.perform
User.all.each do |u|
...
Do Long Operations (Unsafe to kill)
...
# Here it's safe to break the worker and restart
end
end
end
Я завожу это в Resque Scheduler, и это мой конф Bluepill:
...
app.process(process_name) do |process|
process.group = "resque"
process.start_command = "rake environment resque:work QUEUE=foo RAILS_ENV=production"
...
process.stop_signals = [:quit, 5.seconds, :term, 1.minute, :kill]
process.daemonize = true
process.start_grace_time = 30.seconds
process.stop_grace_time = 80.seconds
process.monitor_children do |child_process|
child_process.stop_command = "kill -QUIT {{PID}}"
child_process.checks :mem_usage, :every => 30.seconds, :below => 500.megabytes, :times => [3,4], :fires => :stop
end
end
....
Я бы хотел, чтобы Bluepill или Resque подождали, пока он не достигнет "безопасного" блока для перезапуска или выключения. Как этого добиться?
1 ответ
Попробуйте это так:
1) Установите Resque, чтобы грациозно убивать детей в TERM/INT с помощью new_kill_child
метод по настройке TERM_CHILD
а также RESQUE_TERM_TIMEOUT
Переменные env при запуске:
process.start_command = "rake environment resque:work QUEUE=foo RAILS_ENV=production TERM_CHILD=1 RESQUE_TERM_TIMEOUT=20.0"
Значение по умолчанию для RESQUE_TERM_TIMEOUT
4 секунды.
Это заставит рески отправить TERM-сигнал ребенку, дождаться RESQUE_TERM_TIMEOUT
и если ребенок все еще бежит, убейте его. Обязательно
а) установите этот тайм-аут достаточно большим для завершения критического раздела,
б) настроить время ожидания Bluepill TERM в process.stop_signals
быть немного больше чем RESQUE_TERM_TIMEOUT
не убивать работника, пока он ожидает завершения дочернего процесса в критической секции.
2) Обработайте сигнал TERM в дочернем процессе, чтобы аккуратно остановить:
class FooWorker
class << self
attr_accessor :stop
end
@queue = :foo
def self.perform
User.all.each do |u|
...
Do Long Operations (Unsafe to kill)
...
# Here it's safe to break the worker and restart
return if FooWorker.stop
end
end
end
trap('TERM') do
FooWorker.stop = true
end