Ошибка R12 (Тайм-аут выхода) с использованием рекомендованной Heroku конфигурации Unicorn

My Unicorn config (скопирован из Документы Heroku):

# config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 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'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end 

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

Но каждый раз, когда dyno перезапускается, мы получаем следующее:

heroku web.5 - - Error R12 (Exit timeout) -> At least one process failed to exit within 10 seconds of SIGTERM

Ruby 2.0, Rails 3.2, Единорог 4.6.3

Ответ 1

У нас были такие проблемы с Unicorn в течение некоторого времени., мы также получаем случайные ошибки таймаута, хотя мы никогда не видим большой нагрузки и имеем 4 динамика с 4 рабочими каждый (у нас никогда не было очереди запросов). Нам удавалось избавиться от этих ошибок, даже с помощью Heroku. Я чувствую, что даже они не на 100% уверены в оптимальных настройках для Единорога на Героку.

Мы только недавно перешли на Puma, и до сих пор такая хорошая, намного лучшая производительность и никаких лишних тайм-аутов. Одной из других причин, по которым мы перешли на Puma, является то, что я подозреваю, что некоторые из наших случайных тайм-аутов исходят от "медленных клиентов"., Unicorn не предназначен для обработки медленных клиентов.

Я сообщу вам, если мы увидим продолжение успеха с Puma, но пока все хорошо. Переключатель довольно безболезненен, если ваше приложение является потокобезопасным.

Вот настройки puma, которые мы используем. Мы используем "Clustered Mode".

PROCFILE:

web: bundle exec puma -p $PORT -C ./config/puma.rb

puma.rb:

environment ENV['RACK_ENV']
threads Integer(ENV["PUMA_THREADS"] || 5),Integer(ENV["PUMA_THREADS"] || 5)

workers Integer(ENV["WEB_CONCURRENCY"] || 4)
preload_app!

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
end

В настоящее время для WEB_CONCURRENCY установлено значение 4 и PUMA_THREADS установлено значение 5.

Мы не используем инициализатор для DB_POOL, просто используя настройку по умолчанию DB_POOL по умолчанию 5 (следовательно, 5 потоков).

Единственная причина, по которой мы используем WEB_CONCURRENCY в качестве имени переменной среды, так что log2viz сообщает о правильном количестве рабочих. Скорее назовет его PUMA_WORKERS, но что угодно, а не огромная сделка.

Надеюсь, это поможет., снова, сообщит вам, если мы увидим какие-либо проблемы с Puma.

Ответ 2

Ненавижу добавить еще один ответ, особенно тот, который прост, но в конечном итоге, эта проблема для нас устраняла жемчужину "rack-timeout". Я понимаю, что это, вероятно, не лучшая практика, но мне любопытно, есть ли конфликт между временем ожидания стойки и Unicorn и/или Puma (что странно, потому что Heroku рекомендует использовать тайм-аут стойки для использования с Unicorn).

В любом случае Puma отлично работает для нас, но мы все еще видели некоторые случайные необъяснимые тайм-ауты даже после обновления Puma., но удаление тайм-аута в стойку полностью избавилось от проблемы. Очевидно, что мы все еще получаем тайм-ауты, но только для кода, который мы не оптимизировали, или если мы получаем интенсивное использование (в основном, когда вы ожидаете увидеть таймауты). Таким образом, я бы обвинил эту проблему в тайм-аутах в стойке, а не в Unicorn., что противоречит моему предыдущему ответу:)

Надеюсь, это поможет. Если кто-то еще хочет совать дыры в моей теории, не стесняйтесь!