Является ли RAILS_MAX_THREADS чем-то, что Puma устанавливает и масштабирует во время сборки, или мне следует установить это?

Я знаю, что Rails 5 поставляется с Puma (которую мы используем) и будет искать RAILS_MAX_THREADS как переменную среды или по умолчанию 5 потоков, но я получаю ошибки тайм-аута со значением по умолчанию. Я просмотрел свою базу данных и обнаружил, что максимальное количество подключений составляет несколько тысяч.

Это может быть глупо, но это то, что Puma будет устанавливать автоматически и масштабировать в зависимости от своих настроек, или мне нужно явно установить это в переменных среды? Если его нужно установить вручную, какое значение будет для RAILS_MAX_THREADS хорошим?

Я нашел следующее полезным, но не совсем понимаю, что такое масштабируемость:

https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server https://devcenter.heroku.com/articles/concurrency-and-database-connections


person Michael    schedule 26.04.2017    source источник
comment
Какого рода ошибка тайм-аута возникает и при каких обстоятельствах? Это происходит в разработке или в производстве?   -  person Nikolay Shebanov    schedule 18.05.2017
comment
Спасибо @NickShebanov, это происходит в продакшене, когда у нас большие всплески трафика. С тех пор мы увеличили это значение до 25, но все же время от времени наблюдаем его во время всплесков. Мы смягчили это, развернув новый сервер по мере необходимости. Теперь я знаю, что RAILS_MAX_THREADS не масштабируется автоматически, но будет ли установка этого параметра на ~ 100 абсурдной?   -  person Michael    schedule 18.05.2017


Ответы (1)


На самом деле у Puma есть два параметра: количество потоков и количество рабочих. Если немного изменить значение по умолчанию puma.rb, это будет выглядеть так:

# WORKERS_NUM is not a default env variable name
workers Integer(ENV['WORKERS_NUM'] || 1)
max_threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 1)
min_threads_count = max_threads_count
threads min_threads_count, max_threads_count

Количество рабочих - это количество отдельных процессов, которые Puma запускает для вас. Обычно рекомендуется устанавливать его равным количеству ядер процессора на вашем сервере. Вы можете создать больше из них, чтобы обеспечить одновременную обработку большего количества запросов, но рабочие создают дополнительные накладные расходы на память - каждый рабочий запускает копию вашего приложения rails, поэтому обычно вы должны использовать потоки для достижения более высокой пропускной способности.

RAILS_MAX_THREADS - это способ установить количество потоков, которые каждый из ваших воркеров будет использовать под капотом. В приведенном выше примере min_threads_count равно max_threads_count, поэтому количество потоков постоянно. Если вы установите их разные, он будет масштабироваться от минимума до максимума, но я не видел этого в дикой природе.

Есть несколько причин ограничить количество потоков - ваш интерпретатор и время ответа:

  1. Если вы используете MRI, ваши потоки ограничены GIL, поэтому они не работают параллельно. МРТ имитирует параллельное выполнение путем переключения контекста. Большое количество потоков позволит использовать гораздо больше одновременных подключений, но среднее время отклика увеличится из-за GIL.
  2. Ограничения платформы: т.е. heroku имеет ограничения на количество потоков https://devcenter.heroku.com/articles/dynos#process-thread-limits, Linux ограничивает только количество процессов Максимальное количество потоков на процесс в Linux?.
  3. Когда код не является потокобезопасным, есть вероятность, что использование более одного потока приведет к непредсказуемым проблемам. На самом деле это мой случай, поэтому я особо не экспериментировал с количеством потоков.

Также был аргумент, что медленный ввод-вывод блокирует процесс ruby ​​и не позволяет переключение контекста (то есть вызовы внешних служб или создание больших файлов на лету), но оказалось, что это не так http://yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/. Но оптимизация вашей архитектуры для выполнения как можно большего объема работы в фоновом режиме - это всегда хорошая идея.

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

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

Подводя итог: умножение WORKERS_NUM на RAILS_MAX_THREADS дает максимальное количество одновременных подключений, которые может обрабатывать puma. Если число слишком мало, ваши пользователи увидят тайм-ауты во время скачков нагрузки. Для достижения максимальной производительности при использовании MRI вам необходимо установить WORKERS_NUM на количество ядер и найти оптимальное RAILS_MAX_THREADS на основе среднего времени отклика во время тестов производительности.

person Nikolay Shebanov    schedule 18.05.2017
comment
Вы, без сомнения, находка - person Michael; 23.05.2017
comment
@Michael, пожалуйста, но имейте в виду, что это очень предвзятый ответ, если копнуть глубже, некоторые детали могут отличаться от того, что я сказал. Я просто попытался приспособить это к вашему конкретному случаю. Также я сделал пару ошибок (исправлено): 1. переключение контекста увеличивает среднее время отклика, а не уменьшает, конечно, 2. блокирование ввода-вывода все еще позволяет переключить нить. - person Nikolay Shebanov; 23.05.2017
comment
Я думаю, что каждый воркер получает новый пул соединений, поэтому, если у вас есть 2 воркера с 5 потоками, вам понадобится только 5 пулов соединений (а не 10). Поправьте меня, если я кого-то не прав? - person Sean; 07.04.2018
comment
@ Шон, да, это правильно. Что-то не так с текстом выше? - person Nikolay Shebanov; 07.04.2018
comment
Я только что прочитал ваш последний абзац, в котором говорится, что worker_num, умноженный на rails_max_threads, дает вам максимальное количество одновременных подключений, которые может обрабатывать puma. Хотя это правда, я вижу, как это можно рассматривать как способ расчета размера пула соединений, когда на самом деле вы должны просто использовать свой номер RAILS_MAX_THREADS в качестве размера пула. - person Sean; 07.04.2018