web-dev-qa-db-ja.com

TERMをトラップしてQUITを送信した後のHerokuでのUnicorn終了タイムアウト

Unicornとsidekiqを実行しているHerokuアプリでR12ExitTimeoutエラーが発生します。これらのエラーは、1日に1〜2回、展開するたびに発生します。 Unicornが正しく応答するには、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

タイムアウトする前に、すべての子プロセスが正常に刈り取られたようです。マスターがまだ生きている可能性はありますか?また、ログに示されているように、ルーターはシャットダウン中に引き続きWeb要求をdynoに送信する必要がありますか?

FWIW、Herokuのゼロダウンタイムデプロイメントプラグインを使用しています( https://devcenter.heroku.com/articles/labs-preboot/ )。

90
middkidd

カスタムシグナル処理がここでのタイムアウトの原因だと思います。

編集:Herokuのドキュメントに同意できないことに反対しているので、これに対処したいと思います。

TERMシグナルをキャッチして飲み込むようにUnicornアプリケーションを構成することが、アプリケーションがハングして正しくシャットダウンしない原因である可能性が最も高いです。

Herokuは、[〜#〜] term [〜#〜]シグナルをキャッチして[〜#〜] quit [〜#〜]シグナルに変換すると主張しているようです。ハードシャットダウンを正常なシャットダウンに変える正しい動作。

ただし、これを行うと、場合によってはシャットダウンがまったく行われないリスクが発生するようです。これがこのバグの原因です。 Unicornを実行しているdynoがぶら下がっているユーザーは、証拠を検討し、ドキュメントだけでなく、第一原理に基づいて独自の決定を行う必要があります。

4
Winfield