Выжимаем максимум скорости из PHP
О чем статья
Когда дело доходит до запуска PHP-приложений, выбор правильного веб-сервера критически важен. Чтобы достоверно оценить производительность популярных серверов мы тестировали их не на синтетических, а на реальных данных. Мы не хотели составлять свой рейтинг веб-серверов для запуска php-приложений. Нашей задачей было показать условия, при которых тот или иной веб-сервер продемонстрирует лучшие результаты.
Приложения для запуска php: 30 лет эволюции
В начале был CGI. Это была одна из первых технологий для запуска серверных скриптов, появившаяся в 90-х. CGI поддерживает разные языки, что делает этот интерфейс весьма универсальным, но со своими недостатками. Например, на каждый запрос сервер создает отдельный процесс для каждого CGI-скрипта, что приводит к перерасходу системных ресурсов и сильно сказывается на производительности и скорости ответа сервера. Известной проблемой также является запуск скрипта с правами пользователя веб-сервера. Т.е. при неправильной настройке сервера CGI-скрипт может получить доступ не только к файлам и ресурсам другого приложения, но и к логам и конфигурации сервера, что создает потенциальную уязвимость.
Чтобы решить эти проблемы, был разработан Apache и модуль mod_php, который позволил запускать PHP-код непосредственно внутри веб-сервера и настроить индивидуальные права доступа к файлам для каждого хоста. Хотя на каждый запрос по-прежнему создавался отдельный процесс, часть данных кэшировалась, что существенно ускоряло выполнение по сравнению с CGI. Это давало значительный прирост в скорости.
Apache + mod_php стал популярен благодаря своей простоте конфигурации. Apache до сих пор является одним из популярных веб-серверов для web и часто используется для создания чего-то на скорую руку и без особого конфигурирования.
Популярность и доли рынка web-серверов.
Но использовать Apache для отдачи статики не лучшее решение: даже для получения картинки будет использован «тяжелый» (со всеми модулями вроде mod_php) обработчик.
Хорошей практикой считается использование Apache вместе с Nginx. Nginx эффективно справляется с отдачей статики, а запросы требующие выполнения php кода перенаправляет на Apache. Это значительно уменьшает потребление памяти и повышает скорость обработки запросов.
Схема обработки запроса web-сервером.
Связка Nginx и Apache с mod_php дает значительный прирост производительности, но модуль mod_php имеет узкое место: он запускает интерпретатор php в контексте каждого процесса Apache, что сильно увеличивает использование ресурсов.
Для более эффективного выполнения php был разработан PHP-FPM (FastCGI Process Manager) — это расширенная версия FastCGI, разработанная для увеличения производительности и надежности в средах с высокой нагрузкой. В отличие от mod_php, FPM запускает пул рабочих процессов, которые обслуживают запросы независимо от самого веб-сервера. Нужно иметь в виду, что для получения максимального быстродействия требуется детальная настройка. Также стоит учесть что некоторые CMS (WordPress, 1С-Битрикс: Управление сайтом) потребуют дополнительного конфигурирования так как часть правил хранится в файлах .htaccess (т.е. рассчитаны на запуск именно через Apache).
Можно ли что то еще сделать для ускорения работы PHP-скриптов? Этот вопрос задал себе не один разработчик. В поисках решения были найдены технологии, которые кардинально изменили подход к обработке запросов:
-
Поддержка долгоживущих процессов. В отличии от традиционного подхода где приложение инициализируется каждый раз при новом запросе, можно один раз загрузить все приложение в память и использовать для обработки входящих запросов.
-
HTTP-сервер на уровне приложения. Устраняет дополнительный слой между сервером и приложением, снижая накладные расходы.
-
Многопоточность. Позволяет приложениям обрабатывать больше запросов одновременно в рамках одного процесса.
-
Минимизация накладных расходов на взаимодействие с FastCGI. Убирая взаимодействие с FastCGI и работая с 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
Env-переменные
Параметр |
Значение |
APP_ENV |
production |
APP_DEBUG |
false |
RESPONSE_CACHE_ENABLED |
true |
Кэширование конфигов и роутов
- «php artisan optimize»
Среда тестирования
Virtualization |
WSL |
CPU |
8 cores (2.8GHz) |
RAM |
8Gb |
OS |
Ubuntu |
Конфигурация MySQL
Параметр |
Значение |
tmp_table_size |
512M |
max_heap_table_size |
512M |
sort_buffer_size |
64M |
read_rnd_buffer_size |
1M |
max_connections |
500 |
max_user_connections |
500 |
Все контейнеры и результаты замеров опубликованы в нашем GitHub.
Инструменты тестирования
Само тестирование проводилось с помощью Yandex Tank при следующей конфигурации:
load_profile:
load_type: rps
schedule: line(10, 300, 60s) const(100, 60s)
instances: 300
В данном случае мы явно ограничивает Yandex Tank в количестве инстансов, чтобы не добиться появления 110 кодов ответов, а проверить какой RPS способен выдавать сервер в заданной конфигурации.
В рамках тестирования мы проверяли следующие сервера приложений:
-
Apache(mod_php)
-
PHP-FPM
-
FrankenPHP
-
RoadRunner
-
Swoole
-
Nginx-UNIT
PHP-PM не участвовал в сравнении так как последний релиз был в 2022 и сейчас часть классов из пакета React\Http не совместима с новыми версиями Psr\Http.
Общие результаты тестирования
Тип |
AVG CPU (%) |
AVG RAM (mb) |
AVG RPS |
Результат yandex tank |
Swoole |
45 |
752 |
152.5 |
|
FrankenPHP |
68 |
954 |
140.7 |
|
RoadRunner |
60 |
638 |
131.5 |
|
Nginx Unit |
87 |
2384 |
39.1 |
|
Apache+mod_php |
89 |
5277 |
37.5 |
|
PHP-FPM |
87 |
3500 |
37.3 |
Нагрузка на CPU
График использование памяти
График времени ответа сервера
Для более корректного сравнения серверов стоит разделить их на две группы:
-
Сервера, которые инициализируют приложение при каждом запросе: 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 мс.
Результат тестирования phpinfo с Apache+mod_php
Результат тестирования phpinfo с PHP-FPM
Тестирование сложных приложений, таких как Bagisto, показывает, что при динамических нагрузках разница между PHP-FPM и mod_php минимальна.
Во второй группе (FrankenPHP, Swoole, RoadRunner) — долгоживущие процессы. Они обеспечивают существенное снижение потребления ресурсов и значительный прирост RPS по сравнению с первой группой. Однако важно учитывать, что приложение должно быть адаптировано для работы с серверами, которые загружаются в память один раз и продолжают функционировать без повторной инициализации.
Сообщество и поддержка
Приложения, такие как Swoole, RoadRunner, FrankenPHP и Nginx Unit, пользуются активной поддержкой сообщества разработчиков. Давайте сравним уровень этой поддержки.
Сервер |
Количество звезд |
Количество мейнтейнеров |
Количество релизов (за год) |
Количество созданных issue (за год) |
Процент закрытых issue |
18.4k |
151 |
5 |
207 |
95 |
|
7.9k |
53 |
20 |
112 |
74 |
|
6.8k |
83 |
20 |
366 |
73 |
|
5.4k |
46 |
7 |
236 |
61 |
Выводы
-
Apache mod_php лучше использовать вместе с Nginx в качестве сервера для статики в проектах где нет серьезных нагрузок и ничего не хочется конфигурировать.
-
PHP-FPM оптимален для большинства стандартных и даже высоконагруженных проектов благодаря широкому использованию и активной поддержке сообщества.
-
NGINX Unit обеспечивает производительность, близкую к PHP-FPM, но обладает дополнительными преимуществами — поддержка нескольких языков и возможность запуска нескольких серверов, что делает его отличным выбором для микросервисных архитектур.
Swoole, FrankenPHP и RoadRunner хорошо подходят для высоконагруженных и асинхронных приложений, позволяя использовать долгоживущие процессы и снижая накладные расходы на инициализацию приложения. Однако такие решения требуют, чтобы приложение было адаптировано к работе с долгоживущими процессами. Из трех решений Swoole выделяется как наиболее популярное в сообществе и демонстрирует лучшую производительность и более низкое потребление ресурсов в наших тестах.
Статьи по теме
- аренда команды (от 2 человек, не менее 3 месяцев);
- итерации с фиксированной ценой (1-3 месяца длительностью).
- регулярные онлайн-планерки с заказчиком;
- квалифицированных специалистов;
- организованную команду (находятся в одном помещении, что упрощает решение рабочих вопросов);
- полную прозрачность и регулярность отчетов о результатах.
- нагруженный интернет-магазин;
- личный кабинет;
- оптовые продажи — B2B-платформа;
- маркетплейс;
- технический аудит сайта;
- Битрикс24 — корпоративные HR-порталы;
- Битрикс24 — построение CRM-системы;
- Битрикс24 — личные кабинеты сотрудников;
- Битрикс24 — аудит портала;
- 1С — интеграция с другими системами;
- 1С — доработка системы;
- маркетинг — комплексное интернет-продвижение;
- маркетинг — продвижение для B2B.