При запуске PHP-приложений крайне важно правильно выбрать веб-сервер. Чтобы объективно оценить производительность популярных решений, мы проводили тестирование не на искусственных данных, а на реальных примерах. Наша цель не заключалась в создании рейтинга веб-серверов для PHP-приложений. Мы стремились показать, в каких условиях каждый сервер сможет продемонстрировать наилучшие результаты.
Приложения для запуска php: 30 лет эволюции
Вначале появилась технология CGI, ставшая одной из первых для запуска серверных скриптов еще в 90-х. CGI поддерживала различные языки программирования, что делало её универсальной, но с определёнными недостатками. Например, для каждого запроса сервер создавал отдельный процесс для выполнения CGI-скрипта, что вызывало высокий расход системных ресурсов и снижало производительность, замедляя отклик сервера. Дополнительной проблемой был запуск скриптов с правами пользователя веб-сервера. Это означало, что при неправильной настройке CGI-скрипт мог получить доступ не только к данным других приложений, но и к конфигурационным файлам или логам сервера, создавая серьёзные уязвимости.
Чтобы устранить эти недостатки, был разработан сервер Apache и модуль mod_php. Он позволял выполнять PHP-код непосредственно внутри веб-сервера, а также задавать индивидуальные права доступа к файлам для каждого хоста. Хотя на каждый запрос по-прежнему создавался отдельный процесс, часть данных кэшировалась, что значительно ускоряло обработку запросов по сравнению с CGI. Это обеспечивало заметный прирост производительности.
Связка Apache и mod_php быстро завоевала популярность благодаря простой настройке. Apache остаётся востребованным веб-сервером и по сей день, особенно для проектов, требующих быстрой реализации и минимальной конфигурации.
Apache не является лучшим выбором для отдачи статических файлов: даже для простой выдачи изображения используется «тяжеловесный» обработчик со всеми подключенными модулями, такими как mod_php.
Более эффективным решением считается использование Apache совместно с Nginx. В этой связке Nginx отвечает за обработку статических файлов, а запросы, требующие выполнения PHP-кода, перенаправляются на Apache. Такой подход позволяет существенно снизить потребление памяти и ускорить обработку запросов.
Работа веб-сервера в связке Nginx и Apache с использованием mod_php демонстрирует значительное увеличение производительности. Однако mod_php имеет свой недостаток: каждый процесс Apache запускает PHP-интерпретатор, что приводит к значительному росту потребления ресурсов.
Для повышения эффективности работы PHP был создан PHP-FPM (FastCGI Process Manager) — улучшенная версия FastCGI, предназначенная для увеличения производительности и надежности в условиях высокой нагрузки. В отличие от mod_php, PHP-FPM запускает пул процессов, обслуживающих запросы независимо от веб-сервера. Однако, чтобы достичь максимальной производительности, требуется тщательная настройка. Кроме того, нужно учитывать, что некоторые CMS (например, WordPress или 1С-Битрикс: Управление сайтом) могут потребовать дополнительной конфигурации, так как часть правил работы указывается в файлах .htaccess, рассчитанных на использование Apache.
Но можно ли сделать что-то еще для ускорения работы PHP-скриптов? Этот вопрос волновал не одного разработчика. В поисках решения были найдены технологии, которые кардинально изменили подход к обработке запросов:
-
Поддержка долгоживущих процессов. В отличии от традиционного подхода где приложение инициализируется каждый раз при новом запросе, можно один раз загрузить все приложение в память и использовать для обработки входящих запросов.
-
HTTP-сервер на уровне приложения. Устраняет дополнительный слой между сервером и приложением, снижая накладные расходы.
-
Многопоточность. Позволяет приложениям обрабатывать больше запросов одновременно в рамках одного процесса.
-
Минимизация накладных расходов на взаимодействие с FastCGI. Убирая взаимодействие с FastCGI и работая с php кодом нативно мы устраняем накладные расходы на обработку каждого запроса.
Рассмотрим плюсы и минусы некоторых способов запуска php приложений:
1. Apache + mod_php
Создатель: Apache Software Foundation. Написан на C.
Плюсы:
-
Лёгкость настройки. mod_php включен в в стандартную сборку apache.
-
Стабильность. Решение проверено временем и имеет большую базу готовых проектов.
Минусы:
-
Ресурсоемкость. Модуль загружается внутри каждого процесса Apache, что сильно влияет на производительность.
-
Большое увеличение потребляемых ресурсов при высоких нагрузках.
-
Отсутствие гибкости. Не позволяет тонко настроить конфигурацию для каждого виртуального хоста или разделение ресурсов между процессами.
2. PHP-FPM (PHP FastCGI Process Manager)
Создатель: Андрей Павлин. Написан на C.
Плюсы:
-
Стал официальной частью PHP, начиная с версии 5.3.
-
№2 в списке популярных способов запуска PHP-приложений.
-
Обладает неплохой производительностью за счет масштабирования пула воркеров.
-
Возможность гибкой настройки пула.
-
Больше возможностей для отладки, включая лог медленных запросов.
Минусы:
-
Более сложная настройка по сравнению с Apache(mod_php).
-
Необходимо настроить взаимодействие с веб-сервером (Nginx).
-
Ресурсоемкость: Каждый запрос обрабатывается отдельным PHP-процессом, что увеличивает расход оперативной памяти при высокой нагрузке. Также присутствуют накладные расходы из-за коммуникации через FastCGI.
3. PHP-PM (PHP Process Manager)
Создатель: Марк Шличтенмайер. Написан на PHP.
Плюсы:
-
Поддержка долгоживущих процессов. Вследствие чего производительность лучше чем у php-fpm.
-
Асинхронная обработка. PHP-PM использует ReactPHP для обеспечения асинхронности, что значительно ускоряет обработку запросов.
-
Автоматическая перезагрузка при изменении кода.
Минусы:
-
Необходимо следить за памятью.
-
Требует более глубокого понимания работы асинхронного PHP.
-
Небольшое сообщество.
-
Меньше совместимости: Не поддерживает все библиотеки и расширения, использующие синхронные механизмы, такие как PDO или CURL, которые по умолчанию работают в синхронном режиме.
4. FrankenPHP
Создатель: Кевин Дюнглас. Написан на Go.
Плюсы:
-
Поддержка долгоживущих процессов.
-
Нет необходимости в отдельном веб-сервере.
-
Поддерживает асинхронную обработку запросов.
-
Поддержка WebSocket и длительных соединений.
-
Поддерживается в laravel octane (библиотека позволяющая одной командой установить Swoole, RoadRunner или FrankenPHP, без необходимости писать код воркера) (https://github.com/laravel/octane).
Минусы:
-
Необходимо следить за памятью.
-
Необходимо перезапускать при изменении кода.
-
Требует более глубокого понимания работы асинхронного PHP.
-
Небольшое сообщество.
-
Без использования laravel octane необходимо написать код для воркера.
-
Сложная настройка. Требует более сложной настройки и внедрения в существующие проекты по сравнению с традиционными решениями например php-fpm.
5. RoadRunner
Создатель: Spiral Scout. Написан на Go.
Плюсы:
-
Поддержка долгоживущих процессов.
-
Нет необходимости в отдельном веб-сервере.
-
Асинхронность и многопоточность: поддерживает асинхронные задачи.
-
WebSocket и gRPC: Поддерживает WebSocket, gRPC и очереди для построения реальных асинхронных приложений.
-
Поддерживается в laravel octane.
Минусы:
-
Необходимо следить за памятью.
-
Необходимо перезапускать при изменении кода.
-
Требует более глубокого понимания работы асинхронного PHP.
-
Небольшое сообщество.
-
Без использования laravel octane необходимо написать код для воркера.
-
Сложная настройка.
6. Swoole
Создатель: Swoole Team. Написан на C.
Плюсы:
-
Поддержка долгоживущих процессов.
-
Нет необходимости в отдельном веб-сервере.
-
Поддерживает асинхронный ввод/вывод и корутины, и может обрабатывать высоко-конкурентные запросы.
-
Поддержка множества сетевых протоколов, таймеров, управления процессами, управления памятью и других функций, отвечающих различным потребностям разработки.
-
Поддерживается в laravel octane.
Минусы:
-
Необходимо следить за памятью.
-
Необходимо перезапускать при изменении кода.
-
Требует более глубокого понимания работы асинхронного PHP.
-
Небольшое сообщество.
-
Без использования laravel octane необходимо написать код для воркера.
-
Сложная настройка.
7. NGINX Unit
Создатель: NGINX. Написан на C.
Плюсы:
-
Unit поддерживает не только PHP, но и другие языки, такие как Python, Go, Perl и Ruby.
-
Поддерживает динамическую смену конфигурации без перезапуска сервера.
-
Можно запускать несколько приложений одновременно, что удобно для микросервисов.
-
Минимизирует время простоя и облегчает управление конфигурациями.
-
Не требуется изменять приложение как в случае с долгоживущими процессами.
Минусы:
-
Меньшая производительность по сравнению с решениями для долгоживущих процессов.
-
Небольшое сообщество: Unit менее популярен по сравнению с традиционными решениями вроде PHP-FPM.
-
Ограниченные возможности для асинхронности: Хотя Unit поддерживает несколько языков и конфигураций, он все еще уступает в плане асинхронных возможностей таким решениям, как Swoole или RoadRunner.
Сравнение скорости приложений
На тему сравнения скорости приложений для запуска PHP написано множество статей и проведена уйма тестов. Например:
-
Сравниваем PHP FPM, PHP PPM, Nginx Unit, React PHP и RoadRunner
-
Mod_php vs php-fpm Performance Benchmark [Surprising Results]
-
Apache & PHP system resource usage | mpm_prefork + mod_php vs. mpm_event + php-fpm
Однако большая часть таких тестов являются сильно синтетическими, т.е. тестируемые проекты мало похожи на то, с чем вы в итоге будете иметь дело (например, первая статья, где сервер отвечает json`ом без запросов к БД или вторая, где тестируется phpinfo). Чтобы сделать тесты более реалистичным мы взяли интернет-магазин на базе Laravel (Laravel Framework 10.41.0) — Bagisto (v2.2.2). Сгенерировали 5000 товаров и настроили его в соответствии с инструкциями по развертыванию (включен кэш и отключен различный дебаг).
Env-переменные
Кэширование конфигов и роутов
-
«php artisan optimize»
Среда тестирования
Конфигурация MySQL
Все контейнеры и результаты замеров опубликованы в нашем GitHub.
Инструменты тестирования
Само тестирование проводилось с помощью Yandex Tank при следующей конфигурации:
В данном случае мы явно ограничивает Yandex Tank в количестве инстансов, чтобы не добиться появления 110 кодов ответов, а проверить какой RPS способен выдавать сервер в заданной конфигурации.
В рамках тестирования мы проверяли следующие сервера приложений:
-
Apache(mod_php)
-
PHP-FPM
-
FrankenPHP
-
RoadRunner
-
Swoole
-
Nginx-UNIT
PHP-PM не участвовал в сравнении так как последний релиз был в 2022 и сейчас часть классов из пакета React\Http не совместима с новыми версиями Psr\Http.
Общие результаты тестирования
Для более корректного сравнения серверов стоит разделить их на две группы:
-
Сервера, которые инициализируют приложение при каждом запросе: Apache mod_php, PHP-FPM, Nginx Unit.
-
Сервера с долгоживущими процессами, которые загружают приложение один раз и продолжают с ним работать: FrankenPHP, Swoole, RoadRunner.
В первой группе (Apache mod_php, PHP-FPM, Nginx Unit) разница в RPS незначительна. Однако PHP-FPM и Nginx Unit более эффективны в плане использования ресурсов.
В тестах часто сравнивают PHP-FPM и mod_php, используя статичные данные (например, вывод phpinfo). В таких случаях PHP-FPM действительно демонстрирует прирост производительности в 300%+, что актуально только для статичных данных.
Примеры тестирования вывода phpinfo:
-
PHP-FPM – https://clck.ru/3DeQ32
-
Apache+mod_php – https://clck.ru/3DeQbP
Время ответа от сервера в случае с Apache возрастает до 8 сек. В то время как PHP-FPM стабильно отдает страницы за 200-300 мс.
Тестирование сложных приложений, таких как Bagisto, показывает, что при динамических нагрузках разница между PHP-FPM и mod_php минимальна.
Во второй группе (FrankenPHP, Swoole, RoadRunner) — долгоживущие процессы. Они обеспечивают существенное снижение потребления ресурсов и значительный прирост RPS по сравнению с первой группой. Однако важно учитывать, что приложение должно быть адаптировано для работы с серверами, которые загружаются в память один раз и продолжают функционировать без повторной инициализации.
Сообщество и поддержка
Приложения, такие как Swoole, RoadRunner, FrankenPHP и Nginx Unit, пользуются активной поддержкой сообщества разработчиков. Давайте сравним уровень этой поддержки.
Выводы
-
Apache mod_php рекомендуется использовать вместе с Nginx в качестве сервера для статики в проектах, где нет больших нагрузок и требуется минимальная настройка.
-
PHP-FPM является оптимальным выбором для большинства типовых и даже высоконагруженных проектов благодаря его популярности и активной поддержке сообщества.
-
NGINX Unit обеспечивает производительность, сравнимую с PHP-FPM, но обладает дополнительными преимуществами: поддержка нескольких языков программирования и возможность работы с несколькими серверами. Это делает его особенно подходящим для микросервисных архитектур.
Swoole, FrankenPHP и RoadRunner отлично подходят для высоконагруженных и асинхронных приложений, так как позволяют работать с долгоживущими процессами и сокращают издержки на инициализацию приложения. Однако использование таких решений требует адаптации приложения для работы с долгоживущими процессами. Из этих трёх решений Swoole выделяется своей популярностью в сообществе, а также демонстрирует лучшую производительность и более низкое потребление ресурсов в проведённых тестах.
Наши решения и внедрения успешно зарекомендовали себя в крупных Enterprise-проектах. Мы гордимся, что наш опыт подтвержден сотрудничеством с ведущими компаниями, реализующими масштабные и сложные задачи. Ознакомиться можно здесь.
А если ты талантливый программист и тоже хочешь работать над большими проектами, то ознакомься с нашими актуальными вакансиями – возможно, это именно то, что ты искал! 🙂
ссылка на оригинал статьи https://habr.com/ru/articles/869610/
Добавить комментарий