Tiempo de espera de salida de unicornio en Heroku después de atrapar TERM y enviar QUIT

90

Recibo errores de R12 Exit Timeout para una aplicación Heroku que ejecuta unicorn y sidekiq. Estos errores ocurren 1-2 veces al día y cada vez que implemento. Entiendo que necesito convertir las señales de apagado de Heroku para que unicorn responda correctamente, pero pensé que lo había hecho en la siguiente configuración de unicornio:

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

Mis registros que rodean el error se ven así:

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 los procesos secundarios se cosecharon con éxito antes del tiempo de espera. ¿Es posible que el maestro siga vivo? Además, ¿debería el enrutador seguir enviando solicitudes web al banco de pruebas durante el apagado, como se muestra en los registros?

FWIW, estoy usando el complemento de implementación de tiempo de inactividad cero de Heroku ( https://devcenter.heroku.com/articles/labs-preboot/ ).

middkidd
fuente
6
Si ayuda, también estoy experimentando este problema sin el complemento de implementación de tiempo de inactividad cero. Espero que alguien pueda ayudar o que pueda publicar una respuesta si lo averigua. ¿Quizás contactar al soporte de Heroku?
Chris Peters
Al igual que Chris, no estoy usando tiempo de inactividad cero y estoy experimentando este problema. Esto es a pesar de usar la configuración de unicornio recomendada por Heroku.
imderek
Tengo el mismo problema, a pesar de usar la configuración recomendada de Heroku. Tampoco hay implementación sin tiempo de inactividad.
elsurudo
El mismo problema aquí, y no usa el complemento de prearranque.
Adrian Macneil
Una cosa que he notado es que esto generalmente sucede en dynos de trabajador. No siempre, pero por lo general.
Chris Peters

Respuestas:

4

Creo que su manejo de señal personalizado es lo que está causando los tiempos de espera aquí.

EDITAR: Me votan en contra por no estar de acuerdo con la documentación de Heroku y me gustaría abordar esto.

Configurar su aplicación Unicorn para capturar y tragar la señal TERM es la causa más probable de que su aplicación se cuelgue y no se cierre correctamente.

Heroku parece argumentar que captar y transformar una señal TERM en una señal QUIT es el comportamiento correcto para convertir un apagado forzado en un apagado elegante.

Sin embargo, hacer esto parece introducir el riesgo de que no se apague en absoluto en algunos casos, la raíz de este error. Los usuarios que experimenten dynos colgantes que ejecutan Unicorn deben considerar la evidencia y tomar su propia decisión basándose en los primeros principios, no solo en la documentación.

Winfield
fuente
2
La documentación de Heroku todavía cubre " Cierre elegante con SIGTERM ", y no veo una mención de que ya no sea necesario hacer esto en la pila Cedar. ¿Tiene una referencia de dónde se puede encontrar?
Dennis
No puedo encontrar ninguna documentación que respalde esta respuesta. De acuerdo con la documentación de Unicorn y Heroku, Unicorn todavía usa el reverso de la interpretación de la señal POSIX.
Josh Kovach
Esto no es verdad. Unicorn todavía no se apaga correctamente sin un manejo explícito de la señal TERM. El artículo del Centro de desarrollo que respalda esto se puede encontrar aquí: devcenter.heroku.com/articles/rails-unicorn#config
slant
Reconozco que los documentos de Heroku dicen que debería intentar capturar / transformar estas señales. Los intentos de apagar correctamente son la causa principal más probable de los tiempos de espera de apagado.
Winfield