2013-07-28 4 views
17

Мне нужна помощь с моей конфигурацией Puma (Multi-Thread + Multi-Core Server) в моем приложении RoR4 Heroku. Документы Heroku об этом не совсем актуальны. Я последовал за этим: Concurrency and Database Connections для конфигурации, в которой не упоминается конфигурация кластера, поэтому мне пришлось использовать оба типа вместе (многопоточные и многострочные).Конфигурация кластера Puma на 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 

Вопросы:

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

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

+0

Когда дело доходит до настройки количества нитей. Я прочитал учебник по настройке работника Unicorn, который предложил запустить «ab» и увеличивать количество сотрудников (поток в вашем случае) до тех пор, пока не произойдет снижение производительности (запросы требуют больше времени для завершения). Хорошо сделать довольно динамичную страницу и посмотреть, как действуют разные запросы/параллельные пропорции (также имейте в виду, что если вы делаете много запросов, герою может вырезать вас, подозревая DoS) –

+0

@MichaelSzyndel Итак, я в основном должен идти первым, хотя каждый рабочий , проверить производительность, а затем перейти через потоки и проверить еще раз? Разве это не зависит от того, что именно запрашивается? – Nikom

+1

Из того, что я где-то читал, у Героку есть два ядра (4 виртуальных) на дино. Оптимально иметь один процесс на дино, и тогда вам решать, сколько потоков будет выполняться на каждый процесс. То, что я проверил бы с ab. Имейте в виду также, что если вы передадите 521 МБ ОЗУ, Heroku отправит оповещения и обменется на> 1 ГБ (подтвердите с помощью документов heroku). –

ответ

26

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

Обычно нет, но так как вы используете 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 потоков < = ваша переменная окружения DB_POOL не требуется, вы рискуете использовать все соединения с базой данных в пуле, тогда у вас есть поток, требующий подключения, но не может получить его, и вы можете получить старый «ActiveRecord :: ConnectionTimeoutError» не смог получить соединение с базой данных в течение 5 секунд ». ошибка. Это зависит от вашего приложения, но вы вполне можете иметь max>DB_POOL и все в порядке. Я бы сказал, что ваш DB_POOL должен быть, по крайней мере, таким же, как ваше значение min, даже если ваши подключения не загружены (5: 5 потоков не откроют 5 соединений, если ваше приложение никогда не попадает в базу данных).

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

Production Tier позволяет 500, чтобы быть ясно :)

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

+0

Я прав, что «рабочие 2» означает дополнительные рабочие процессы для пумы, так что в целом есть процессы «3»? – gaussblurinc

2

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

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

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

Смежные вопросы