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

В чем разница между работниками и потоками в Puma

В чем разница между работником puma и потоком puma в контексте dynku heroku?

Что я знаю (пожалуйста, поправьте меня, если я ошибаюсь):

  • Тонкий не является одновременным, поэтому веб-процесс может выполнять только один запрос за раз

  • В единороге я знаю, что у меня может быть несколько рабочих единорога в одном процессе, чтобы добавить concurrency.

Но в пуме есть нитки и рабочие. Разве рабочий не является потоком внутри процесса puma?

Можно ли использовать больше рабочих/потоков для добавления web concurrency в Heroku?

4b9b3361

Ответ 1

Как говорится в другом ответе, эта статья статьи Heroku довольно хороша с объяснениями определенных элементов конфигурации.

Однако, если вам нужно настроить приложение на Heroku или где угодно, тогда он платит, чтобы знать, как все работает.

Я думаю, что вы почти правы, когда говорите: "Работник - это поток внутри процесса puma", я считаю, что рабочий - это процесс уровня операционной системы, раздвоенный из puma, который затем может использовать потоки внутри.

Насколько я понимаю - puma будет разветвлять процесс своей операционной системы, но много раз вы устанавливаете конфигурацию workers для ответа на HTTP-запросы. Это дает вам parallelism с точки зрения обработки нескольких запросов, но обычно это занимает больше памяти, так как "копирует" ваш код приложения для каждого рабочего.

Каждый рабочий из puma будет использовать несколько потоков в процессе своей ОС в зависимости от конфигурации threads. Они добавляют concurrency, позволяя процессу puma отвечать на самые многочисленные запросы, так что если один поток заблокирован, то есть обрабатывает запрос, он может обрабатывать новый запрос другим потоком. Как указано, это требует, чтобы все ваше приложение было потоковым, так что, например, любая глобальная конфигурация из одного запроса не "утечка" в другую.

Вы бы настроили puma так, чтобы количество рабочих было достаточным для количества доступных процессоров и памяти, а затем настройте потоки, зависящие от того, сколько вы хотите насытить хост, на котором запущено приложение, и как работает ваше приложение, - больше делает не всегда равны быстрее/большей пропускной способности запроса.

Ответ 2

Это большая область, и я не эксперт, однако...

Puma может порождать многих работников, и каждый рабочий может использовать много потоков для обработки запроса.

Единорог не имеет нитей, насколько я знаю, у него просто рабочая модель.

Если вы используете потоки, вам нужно убедиться, что ваш код является потокобезопасным. Это означает, что Rails, любой драгоценный камень, на который вы положитесь, и собственный код.

Для максимальной производительности вы также можете просмотреть JRuby или Rubinius, которые имеют поддержка резьбы. MRI ограничен его GIL.

Существует хорошая статья о Heroku в которой объясняется, как Puma использует рабочих и потоки. Вы должны, вероятно, прочитать это и игнорировать меня:)

Ответ 3

Я просто хочу подчеркнуть самую важную строку статьи Heroku/Puma, на которую ссылались здесь:

Rails поддерживает свой собственный пул соединений с базой данных, с новым пулом, созданным для каждого рабочего процесса. Потоки внутри работника будут работать в том же пуле.

В нем говорится, что у каждого работника будет свой пул. Тем не мение:

Потоки внутри работника будут работать в том же пуле.

Это очень важно понять. Если работник Puma использует 5 потоков на одного работника, то для database.yml должен быть настроен пул соединений 5, поскольку каждый поток может установить соединение с базой данных.

Поскольку каждый Worker порождается системной fork(), у нового работника будет свой собственный набор из 5 потоков для работы, и, таким образом, для нового созданного экземпляра Rails для database.yml все равно будет установлен пул соединений из 5,

Теперь пул соединений database.yml и ваш реальный пул баз данных - это две разные вещи. ВСЕГО соединения с вашей базой данных должны будут использовать специальную формулу, упомянутую в документах Heroku:

Хорошая формула для определения количества соединений, которые потребуются каждому приложению, заключается в умножении RAILS_MAX_THREADS на WEB_CONCURRENCY.

Это означает, что если вы используете 2 рабочих, каждый из которых имеет 5 потоков, то 2 * 5 = 10, поэтому ваша база данных должна быть настроена на прием 10 одновременных подключений.