Подтвердить что ты не робот

Конфигурация кластера Puma на Heroku

Мне нужна помощь в моей конфигурации Puma (Multi-Thread + Multi-Core Server) в моем приложении RoR4 Heroku. Документы Heroku об этом не совсем актуальны. Я последовал за этим: Concurrency и подключения к базе данных для конфигурации, в которой не упоминается конфигурация кластера, поэтому мне пришлось использовать оба типа вместе (потоковые и многоядерный).

Моя текущая конфигурация:

./PROCFILE

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

./конфигурации/puma.rb

environment production
threads 0,16

workers 4
preload_app!

on_worker_boot do
  ActiveRecord::Base.connection_pool.disconnect!

  ActiveSupport.on_load(:active_record) do
    config = Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
    config['pool']              = ENV['DB_POOL'] || 5
    ActiveRecord::Base.establish_connection
  end
end

Вопросы:

a) Нужна ли мне конфигурация before_fork/after_fork, как в Unicorn, так как рабочие кластера раздвоены?.
б) Как настроить количество потоков в зависимости от моего приложения - в чем причина его отказа?/В каких случаях это может иметь значение? Не оптимизировано ли 0:16?
c) База данных Heroku позволяет 500 подключений. Что было бы хорошим значением для DB_POOL в зависимости от потока, рабочего и динамического счета? - При каждом параллельном работе каждый поток на одного рабочего на динамод требует единственного соединения с БД?

В целом: как должна выглядеть моя конфигурация для concurrency и производительности?

4b9b3361

Ответ 1

a) Мне нужна конфигурация before_fork/after_fork, как в Единорог, так как рабочие кластера раздвоены?.

Обычно нет, но поскольку вы используете preload_app, да. Предварительная загрузка приложения запускает и запускает экземпляр, а затем разворачивает пространство памяти для рабочих; результат состоит в том, что ваши инициализаторы только запускают один раз (возможно, выделяя соединения db и т.д.). В этом случае ваш код on_worker_boot подходит. Если вы не используете preload_app, каждый рабочий загружается сам, и в этом случае использование инициализатора идеально подходит для настройки настраиваемого соединения, как вы делаете. Фактически, без preload_app ваш блок on_worker_boot будет ошибочным, потому что в этот момент ActiveRecord и друзья даже не загружены.

b) Как настроить количество потоков в зависимости от моего приложения - что было бы причиной его падения?/В каких случаях это сделало бы разница? Не оптимизировано ли 0:16?

На Heroku (и моем тестировании) вам лучше всего соответствовать вашим тегам min/max, с настройкой max <= DB_POOL. Потоки min позволяют вашему приложению отжимать ресурсы, когда они не находятся под нагрузкой, что обычно отлично подходит для освобождения ресурсов на сервере, но, вероятно, менее необходимо для Heroku; этот dyno уже предназначен для обслуживания веб-запросов, может также иметь их вверх и готов. При установке переменной окружения max threads <= your DB_POOL не требуется, вы рискуете использовать все соединения с базой данных в пуле, тогда у вас есть поток, требующий подключения, но не могу получить его, и вы можете получить старый "ActiveRecord:: ConnectionTimeoutError", который не смог получить соединение с базой данных в течение 5 секунд ". ошибка. Это зависит от вашего приложения, но вы вполне могли бы иметь max > DB_POOL и быть в порядке. Я бы сказал, что ваш DB_POOL должен быть, по крайней мере, таким же, как ваше значение потоков min, даже если ваши соединения не загружаются с высокой загрузкой (5: 5 потоков не будут открывать 5 соединений, если ваше приложение никогда не попадает в базу данных).

c) База данных Heroku позволяет 500 подключений. Что было бы хорошо значение для DB_POOL в зависимости от потока, рабочего и динамического счета? - Делает каждый поток на одного рабочего на дино требует единственного соединения БД, когда работая параллельно?

Уровень Производственный уровень позволяет получить четкость:)

Каждый поток на одного рабочего на динамод может использовать соединение, в зависимости от того, все ли они пытаются получить доступ к базе данных одновременно. Обычно соединения повторяются, как только они выполняются, но, как я упоминал в b), если вы потоки больше, чем ваш пул, вы можете иметь плохое время. Соединения будут использоваться повторно, все это обрабатывается ActiveRecord, но иногда не идеально. Иногда соединения простаивают или умирают, и поэтому рекомендуется включить Reaper для обнаружения и восстановления мертвых соединений.

Ответ 2

Вы не хотите меньше подключений DB, чем потоки. Помните, что каждый отдельный процесс имеет свой собственный пул соединений, поэтому, если ваша БД поддерживает 20 подключений и вы хотите запустить 2 процесса, большинство потоков, которые вы можете запускать без риска таймаутов, - это 10 потоков с пулом из 10 подключений.

Вы хотите оставить несколько подключений для сеансов консоли rails. Также имейте в виду тех, кто работает в фоновом режиме, и являются ли они потоковыми.

Если ваши работники находятся в отдельном процессе (sidekiq), у них будет свой собственный пул. Если потоки ваших рабочих порождаются из веб-процесса (girl_friday или sucker_punch), вам нужно, чтобы DB_POOL больше максимального количества веб-потоков, так как они будут использовать пул соединений.