Comments 34
Добавлю ложку дегтя к nginx-unit, у него есть свои большие плюсы но так же и минусы:
Дочерние процессы создаются изолировано и вся функциональность mmap а это (opcache, apcu, stream) будут потреблять в x раз больше оперативной памяти. (issues) но есть и плюс, изоляция дает большую стабильность при реактивной нагрузке
Отсутствие мониторинга, невозможно тонко рассчитать количество процессов (issues)
по 1 пункту скоро будут процессы прототипы https://github.com/nginx/unit/commit/e207415a78ae67b937faf7e5bcd6e5192993180a
тут собрана интересная инфа сколько rps вообще может держать пых https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=fortune&l=zik073-sf&c=2
Тут стоит задать вопрос - будете ли вы nginx-unit сразу публиковать наружу в продакшн окружении? Или все же поставите nginx перед ним? А если поставите - то логично тестировать nginx + fpm vs nginx + nginx-unit
На самом деле наша (разработчиков Unit) цель - это довести его по функциональности до, как минимум, паритета с nginx, чтобы можно было без труда всегда выставлять его наружу. Сейчас его приходится ставить перед nginx в тех случаях, когда от nginx нужна некоторая дополнительная функциональность, которая пока ещё отсутствует в Unit.
Но задачу балансировки при более одной ноды решать все равно придется промежуточным сервером. Мой коммент скорее был, что тест в статье меряет не fpm vs unit, а накладные расходы реверс прокси.
Когда нет необходимости преобразовывать протокол, то не обязательно балансировку делать на уровне HTTP. И даже на уровне HTTP можно свести дополнительную задержку к паре миллисекунд. Но тут дело скорее в том, что PHP-FPM сам по себе медленный - там зачем-то делаются лишние сисколы, которых можно было бы избежать. При этом он в целом заброшен и не развивается. А его модель работы с соединениями и запросами - неизбежно вносит дополнительные задержки и успешно схлопывается под нагрузкой, что все и наблюдают при тестировании.
Ну и все же L3 балансировку используют редко когда много трафика и то обычно между L7 балансировщиками. Ибо тривиально балансировать на L7 проще, а порой и эффективнее.
В предыдущем тесте как раз был nginx + fpm vs nginx + unit, и там вполне сопоставимые цифры были на пока не задрали конкурентность.
Вот только nginx там был совершенно не настроен на производительность и снижение задержек. В случае с Unit-ом можно было бы включить кэш keepalive соединений и выкрутить ручку в большое значение - это бы существенно снизило задержки без какого-либо негативного эффекта.
А в случае с PHP-FPM такое нормально работать не может, т.к. каждое keepalive соединение будет удерживать занятым один рабочий процесс c PHP постоянно и он будет простаивать, ожидая запроса конкретно в данном соединении. И если все его рабочие процессы будут заняты keepalive соединениями, то ни одно дополнительное соединение вообще не будет обработано и получим пресловутый "504 Gateway Timeout", как только число одновременных запросов превысит число рабочих процессов PHP-FPM.
И как nginx настраивать с PHP-FPM, если nginx еще и статика отдается?
Раздача статики тут не влияет. А PHP-FPM настройкой nginx-а не исправить.
ну как сказать... вот есть у меня проект, где на текущем жизненном этапе в каждый бэкенд идет примерно 20 запросов в сек .
В бэкенде сидит php который сотрудничает с nginx через php-fpm
и все вполне шустро бегает, даже с отключенным opcache и даже без fastcgi_cache у nginx.
Тонкая настройка параметров nginx и обработка напильником php-fpm.ini до придания надлежайшей формы, помогает держать LA сервера в пределах 3-5.
база данных обычная - mysql с тюнингованным конфигом. на данном этапе вполне справляется с нагрузкой.
Правда у нас работает purePHP без новомодных свистелок, используется строгий формат входных данных - на энтрипойнте сначала проверяется все что надо проверить, шаг влево или вправо - расстрел http_405, а затем уже инклюдим 100500 файлов нужные модули, строго под конкретный запрос.
перед этими сборками будет стоять шина, т.е. они именно в том виде в котором будут за шиной находиться. В связи с этим тестировать nginx + nginx-unit смысла и нет.
Preload использовался?
Жалко не добили с RR. По идеи должно было быть получше чем со swoole
Выводы, если честно, несколько обескураживают.
"Я хорошо разбираюсь в апельсинах, но до кучи решил ещё протестировать яблоки и бананы - взял какие под руку под руку попались. Ну в общем победили апельсины".
К сожалению, я тоже не спец в настройке различных вариантов окружения, и не могу указать на какие-то конкретные недочёты (ну кроме разве что наличия preloading-а, который, по идее, мог немного подтянуть результаты "умирающих" сборок), но мне как раз очень интересно такое сравнение само по себе. Но вот это "я не спец в fpm, взял что попалось" и "octane меня тоже удивил" неизбежно наводят на мысль о том, что результаты могли бы быть и другими.
Но зато я узнал из статьи о существовании Nginx-unit, пойду почитаю как это работает.
Интересно было бы посмотреть ещё на Laravel + RoadRunner и желательно не через кривоватую реализацию через Octane, а через официальный инструмент от разработчиков rr. Мне кажется эта связка могла бы удивить не меньше.
Мы уделяем большое внимание производительности и масштабируемости при разработке Unit-а, поэтому результаты не удивляют. Но, безусловно, есть ещё куда расти, т.к. не все идеи пока ещё реализованы и в будущем версиях показатели будут только улучшаться.
Конфиги присутствуют, но где же код? Хочется получить код приложений и попробовать воспроизвести тестирование.
Какая настройка использовалась для PHP-FPM?
Если по умолчанию, то тогда понятен плохой результат сборки: по умолчанию PHP-FPM поднимает максимум 20 потоков.
Надо первого игрока переконфигурировать и заново протестировать.
В статье указаны настройки PHP-FPM:
memory_limit=512M
pm = static
pm.max_children = 100
pm.max_requests = 1000
И написано, почему значение было увеличено. Вы статью-то читали? :)
Был невнимателен.
Вообщем-то php-fpm надо знать как конфигурить под highload, чтоб потом не удивляться, что это он не держит.
В вашем случае вы заюзали static вместо dynamic и это в целом не правильно, хотя гайды из гугля показывают типа static лучше.
Статик хорош, когда идет равномерная предсказуемая загрузка, которая не будет давать пиков, на которых возникнет 504 gateway error, потому что кончились воркеры.
Я все это проходил: экспериментировал со static, dynamic, ondemand
в итоге dynamic allocation дает лучший результат
рабочий конфиг, который держит около 2М коннектов/сутки к php-fpm
rlimit_files = 1048576
rlimit_core = unlimited
pm = dynamic
pm.max_children = 512
pm.start_servers = 48
pm.min_spare_servers = 48
pm.max_spare_servers = 128
pm.max_requests = 2048
request_terminate_timeout = 600s
php-fpm загнулся со 100 рабочими процессами, где Unit справился всего с 16 и обошел его на порядок. Вы предлагаете накрутить аж 512 процессов, но это же просто костыль, который наглядно демонстрирует насколько php-fpm убогий. Так ведь и Unit-у можно 512 процессов накрутить, но зачем? На сервере всегда есть другие задачи, под которые лучше память выделить.
Сравнение php-fpm, nginx-unit и laravel-octane