Tempo limite de saída do unicórnio no Heroku após capturar TERM e enviar QUIT

90

Estou recebendo erros de Tempo limite de saída R12 para um aplicativo Heroku executando unicórnio e sidekiq. Esses erros ocorrem 1 a 2 vezes por dia e sempre que eu implantar. Eu entendo que preciso converter os sinais de desligamento do Heroku para que o unicórnio responda corretamente, mas pensei que tinha feito isso na configuração do unicórnio abaixo:

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

Meus logs em torno do erro são assim:

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

Parece que todos os processos filho foram colhidos com êxito antes do tempo limite. É possível que o mestre ainda esteja vivo? Além disso, o roteador ainda deve estar enviando solicitações da Web ao dinamômetro durante o desligamento, conforme mostrado nos logs?

FWIW, estou usando o plug-in de implantação com tempo de inatividade zero do Heroku ( https://devcenter.heroku.com/articles/labs-preboot/ ).

middkidd
fonte
6
Se ajudar, também estou tendo esse problema sem o plug-in de implantação com tempo de inatividade zero. Espero que alguém possa ajudar ou você possa postar uma resposta se você descobrir. Talvez entre em contato com o suporte do Heroku?
Chris Peters
Assim como Chris, não estou usando tempo de inatividade zero e estou tendo esse problema. Isso apesar de usar a configuração de unicórnio recomendada do Heroku.
imderek
Estou tendo o mesmo problema, apesar de usar a configuração recomendada do Heroku. Sem tempo de inatividade zero, também.
elsurudo
O mesmo problema aqui, e não usando o plugin de pré-inicialização.
Adrian Macneil
Uma coisa que percebi é que isso GERALMENTE acontece em dinossauros de trabalho. Nem sempre, mas geralmente.
Chris Peters,

Respostas:

4

Acho que seu tratamento de sinal personalizado é o que está causando os tempos limite aqui.

EDIT: Estou sendo reprovado por discordar da documentação do Heroku e gostaria de abordar isso.

Configurar seu aplicativo Unicorn para capturar e engolir o sinal TERM é a causa mais provável de seu aplicativo travar e não desligar corretamente.

Heroku parece argumentar que capturar e transformar um sinal TERM em um sinal QUIT é o comportamento correto para transformar um desligamento forte em um desligamento normal.

No entanto, fazer isso parece apresentar o risco de nenhum desligamento em alguns casos - a raiz desse bug. Os usuários experimentando dinos dinâmicos pendurados executando o Unicorn devem considerar a evidência e tomar suas próprias decisões com base nos primeiros princípios, não apenas na documentação.

Winfield
fonte
2
A documentação do Heroku ainda cobre o " desligamento normal com SIGTERM " e não vejo nenhuma menção de não precisar mais fazer isso na pilha do Cedar. Você tem uma referência de onde isso pode ser encontrado?
Dennis
Não consigo encontrar nenhuma documentação que suporte esta resposta. De acordo com a documentação do Unicorn e do Heroku, o Unicorn ainda usa o reverso da interpretação do sinal POSIX.
Josh Kovach
Isso não é verdade. O Unicorn ainda não fecha normalmente sem o tratamento explícito do sinal TERM. O artigo do Dev Center apoiando isso pode ser encontrado aqui: devcenter.heroku.com/articles/rails-unicorn#config
slant
Reconheço que os documentos do Heroku dizem que você deve tentar capturar / transformar esses sinais. As tentativas de desligamento normal são a causa raiz mais provável dos tempos limite de desligamento.
Winfield