Тайм-аут выхода Unicorn на Heroku после захвата TERM и отправки QUIT

Я получаю ошибки R12 Exit Timeout для приложения Heroku, использующего единорога и sidekiq. Эти ошибки происходят 1-2 раза в день и всякий раз, когда я развертываю. Я понимаю, что мне нужно преобразовать сигналы выключения из Heroku для единорога, чтобы правильно реагировать, но подумал, что я сделал это в конфигурации unicorn ниже:

worker_processes 3
timeout 30
preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts "Unicorn master intercepting TERM and sending myself QUIT instead. My PID is #{Process.pid}"
    Process.kill 'QUIT', Process.pid
  end

  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
    Rails.logger.info('Disconnected from ActiveRecord')
  end
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts "Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT. My PID is #{Process.pid}"
  end

  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
    Rails.logger.info('Connected to ActiveRecord')
  end

  Sidekiq.configure_client do |config|
    config.redis = { :size => 1 }
  end
end

Мои журналы, окружающие ошибку, выглядят следующим образом:

Stopping all processes with SIGTERM
Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT. My PID is 7
Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT. My PID is 11
Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT. My PID is 15
Unicorn master intercepting TERM and sending myself QUIT instead. My PID is 2
Started GET "/manage"
reaped #<Process::Status: pid 11 exit 0> worker=1
reaped #<Process::Status: pid 7 exit 0> worker=0
reaped #<Process::Status: pid 15 exit 0> worker=2
master complete
Error R12 (Exit timeout) -> At least one process failed to exit within 10 seconds of SIGTERM
Stopping remaining processes with SIGKILL
Process exited with status 137

Похоже, что все дочерние процессы были успешно собраны до таймаута. Возможно ли, что хозяин жив? Кроме того, должен ли маршрутизатор по-прежнему отправлять веб-запросы на дино во время выключения, как показано в журналах?

FWIW, я использую плагин для развертывания без использования Heroku (https://devcenter.heroku.com/articles/labs-preboot/).

Ответ 1

Я думаю, что ваша настраиваемая обработка сигналов - вот что вызывает таймауты здесь.

РЕДАКТИРОВАТЬ: Я получаю вниз за несогласие с документацией Heroku, и я хотел бы обратиться к этому.

Конфигурирование приложения Unicorn для захвата и проглатывания сигнала TERM является наиболее вероятной причиной зависания вашего приложения и не отключается правильно.

Heroku, похоже, утверждает, что захват и преобразование сигнала TERM в сигнал QUIT - это правильное поведение, чтобы превратить жесткий выключение в изящное завершение работы.

Однако, в этом случае, как представляется, возникает риск вообще не останавливаться - корень этой ошибки. Пользователи, испытывающие висячие динозавры, использующие Unicorn, должны учитывать доказательства и принимать собственное решение на основе первых принципов, а не только документации.