Мы запускаем веб-приложение Ruby on Rails под Unicorn. Наше приложение не строго связано с процессором (у нас есть двойная система Xeon E5645 с 12 ядрами, а среднее значение пиковой нагрузки составляет около 6). Первоначально мы начали с 40 работниками Unicorn, но со временем объем памяти приложения увеличивался. Итак, теперь нам нужно уменьшить количество рабочих процессов. Я думал, что стандартная формула (количество ядер процессора + 1) применима и к Unicorn, но мой коллега пытался убедить меня, что мы должны зарезервировать больше экземпляров Unicorn для каждого процессора и предоставил эта ссылка. Тем не менее, я не совсем уверен, почему нам нужно тратить столько памяти на простаивающие процессы Unicorn.
Мой вопрос: в чем причина иметь более одного экземпляра Unicorn на ядро процессора? Это связано с какой-то архитектурной особенностью Unicorn? Я знаю, что занятые процессы Unicorn не могут принимать новые соединения (мы используем сокеты домена UNIX для связи с экземплярами Unicorn, кстати), но я думал, что отставание было введено именно для решения этой проблемы. Можно ли каким-либо образом преодолеть эти 2-8 экземпляров Unicorn на одно правило ЦП?
Хорошо, наконец-то я нашел ответ. Оптимальное количество воркеров Unicorn напрямую не связано с количеством ядер ЦП, это зависит от вашей нагрузки и внутренней структуры / скорости реакции приложения. В основном мы используем профилировщик выборки для определения состояния работников, мы стараемся, чтобы рабочие 70% не работали, а 30% выполняли фактическую работу. Итак, 70% образцов должны «ждать вызова select (), чтобы получить запрос от внешнего сервера». Наше исследование показало, что существует всего 3 эффективных состояния рабочих: 0-30% образцов простаивают, 30-50% образцов простаивают и 50-70% образцов бездействуют (да, мы можем получить больше неактивных образцов, но есть в этом нет особого смысла, потому что время отклика приложения существенно не меняется). Мы считаем, что 0–30% - это «красная зона», а 30–50% - «желтая зона».
Вы правы насчет N + 1 для задач, связанных с процессором.
С другой стороны, единорог не использует потоки, поэтому каждая операция ввода-вывода. блокирует процесс, и другой процесс может запускать и анализировать заголовки HTTP, объединять строки и выполнять все задачи с интенсивным использованием ЦП, необходимые для обслуживания пользователя (выполняя это раньше, чтобы уменьшить задержку запроса).
И вы можете захотеть иметь больше потоков / процессов, чем ядер. Представьте себе следующую ситуацию: req. A занимает в десять раз больше, чем требуется. B, у вас есть несколько одновременных запросов A, а быстрый запрос B просто ставится в очередь, ожидая завершения A-req. Поэтому, если вы можете предсказать количество тяжелых запросов, вы можете использовать это число в качестве еще одного ориентира для настройки системы.