Délai de sortie de la licorne sur Heroku après avoir piégé TERM et envoyé QUIT

90

Je reçois des erreurs de délai de sortie R12 pour une application Heroku exécutant unicorn et sidekiq. Ces erreurs se produisent 1 à 2 fois par jour et à chaque fois que je déploie. Je comprends que je dois convertir les signaux d'arrêt de Heroku pour que la licorne réponde correctement, mais je pensais l'avoir fait dans la configuration de la licorne ci-dessous:

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

Mes journaux entourant l'erreur ressemblent à ceci:

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

Il semble que tous les processus enfants ont été correctement récupérés avant l'expiration du délai. Est-il possible que le maître soit toujours en vie? De plus, le routeur doit-il toujours envoyer des requêtes Web au dyno pendant l'arrêt, comme indiqué dans les journaux?

FWIW, j'utilise le plugin de déploiement zéro temps d'arrêt de Heroku ( https://devcenter.heroku.com/articles/labs-preboot/ ).

Middkidd
la source
6
Si cela aide, je rencontre également ce problème sans le plugin de déploiement sans temps d'arrêt. J'espère que quelqu'un pourra vous aider ou que vous pourrez poster une réponse si vous la comprenez. Peut-être contacter le support Heroku?
Chris Peters
Tout comme Chris, je n'utilise aucun temps d'arrêt et je rencontre ce problème. Ceci malgré l'utilisation de la configuration de licorne recommandée par Heroku.
imderek
J'ai le même problème, malgré l'utilisation de la configuration recommandée par Heroku. Pas de déploiement sans temps d'arrêt non plus.
elsurudo
Même problème ici, et ne pas utiliser de plugin de pré-lancement.
Adrian Macneil
Une chose que j'ai remarquée est que cela se produit généralement sur les dynos de travail. Pas toujours, mais généralement.
Chris Peters

Réponses:

4

Je pense que votre gestion de signal personnalisée est ce qui cause les délais d'attente ici.

EDIT: Je suis critiqué pour être en désaccord avec la documentation de Heroku et j'aimerais aborder cela.

La configuration de votre application Unicorn pour capturer et avaler le signal TERM est la cause la plus probable du blocage et de l'arrêt correct de votre application.

Heroku semble soutenir que capturer et transformer un signal TERM en signal QUIT est le bon comportement pour transformer un arrêt brutal en un arrêt progressif.

Cependant, cela semble introduire le risque de ne pas s'arrêter du tout dans certains cas - la racine de ce bogue. Les utilisateurs confrontés à des dynos suspendus exécutant Unicorn doivent prendre en compte les preuves et prendre leur propre décision en fonction des premiers principes, et pas seulement de la documentation.

Winfield
la source
2
La documentation Heroku couvre toujours " Arrêt progressif avec SIGTERM ", et je ne vois aucune mention de ne plus avoir besoin de le faire sur la pile Cedar. Avez-vous une référence à l'endroit où cela peut être trouvé?
Dennis
Je ne trouve aucune documentation qui prend en charge cette réponse. Selon la documentation de Unicorn et Heroku, Unicorn utilise toujours l'inverse de l'interprétation du signal POSIX.
Josh Kovach
Ce n'est pas vrai. Unicorn ne s'arrête toujours pas sans traitement explicite du signal TERM. L'article Dev Center soutenir ce se trouve ici: devcenter.heroku.com/articles/rails-unicorn#config
oblique
Je reconnais que les documents Heroku disent que vous devriez essayer d'attraper / transformer ces signaux. Les tentatives d'arrêt progressif sont la cause première la plus probable des délais d'arrêt.
Winfield