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

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

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

./Procfile

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

./config/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

Вопросы:

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

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


person Miiller    schedule 28.07.2013    source источник
comment
Когда дело доходит до настройки количества потоков. Я читал учебник по настройке воркеров Unicorn, в котором предлагалось запустить ab и увеличить количество воркеров (потоков в вашем случае) до тех пор, пока производительность не упадет (запросы занимают больше времени для выполнения). Хорошо взять довольно динамичную страницу и сначала посмотреть, как действуют разные пропорции запросов/одновременных запросов (также имейте в виду, что если вы делаете много запросов, heroku может отрезать вас от подозрения DoS)   -  person Mike Szyndel    schedule 30.07.2013
comment
@MichaelSzyndel Итак, мне в основном нужно сначала пройти через каждого работника, проверить производительность, а затем просмотреть потоки и снова проверить? Разве это не зависит от того, что именно запрашивается?   -  person Miiller    schedule 31.07.2013
comment
Из того, что я где-то читал, у Heroku два ядра (4 виртуальных) на динамометр. Оптимально иметь один процесс на динамометр, а затем вам решать, сколько потоков запускать для каждого процесса. Что бы я проверил с аб. Имейте также в виду, что если вы передадите 521 МБ ОЗУ, Heroku будет отправлять оповещения, и они будут заменены на > 1 ГБ (подтвердите с документами heroku)   -  person Mike Szyndel    schedule 31.07.2013
comment
Какой тип динамометра вы используете? Вы упомянули: Multi-Thread+Multi-Core Server означает ли это PX dyno (500 долларов в месяц)?   -  person nothing-special-here    schedule 02.06.2015


Ответы (2)


а) Нужна ли мне конфигурация before_fork/after_fork как в Unicorn, так как воркеры Cluster разветвлены?

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

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

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

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

Производственный уровень допускает 500, если быть точным :)

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

person catsby    schedule 01.08.2013
comment
я прав, что workers 2 означает дополнительные рабочие процессы для пумы, так что всего процессов 3? - person gaussblurinc; 10.06.2015

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

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

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

person Duke    schedule 14.08.2015