Сравнение PHP FPM и RoadRunner

Fpm– это ещё одна разновидность серверного Api для языка PHP. Помимо него, есть ещё 3 других технологии:

  • SLI предоставляет возможность работать с интерфейсом командной строки. Инструкции передаются путём ввода текстовых команд в терминал.
  • Apxs2 – небольшая утилита, которая упрощает работу с серверами от Apache.Она помогает устанавливать дополнительные модули, работать с базами данных и создавать файлы DSO.
  • CGI – также предоставляет возможность работать с консолью.

FPM создана разработчиками из компании Badoo. Сегодня новые версии выходят только благодаря сообществу. Расшифровывается как быстрый менеджер процессов. Работа с FPMнемного похожа на работу с HTTP сервером Apache. Отличие в том, что FPM – это не сервер, а чистый PHP код. Этот интерфейс даже не использует HTTP проток для работы. В нём реализован специальный протокол fastcgi. Это позволяет коду на PHP быстро обрабатывать входящие к нему запросы.

Особенности FPM

Так как интерфейс написан на PHP, то ему свойственны все особенности этого языка и серверов, написанных на нём:

  • Один процесс – один запрос. Это основная особенность кода на PHP. Такое решение подвержено Dos атакам. Например, вы держите сервер, на котором есть 100 процессов FPM. Если одновременно подключить 100 пользователей и заставить их скачивать или загружать какой-либо файл, то 101 пользователь при подключении получить ошибку 504. Связано это с тем, что сервер на FPM не будет обрабатывать новый запрос, пока процессы заняты. 100 клиентов даже могут скачивать небольшой файл, главное – растянуть скачивание, чтобы сервер долго висел. Такая проблема свойственна многим веб-сервисам. Например, Dos уязвимости есть и у Apache.
  • Модули, написанные на PHP, подвержены утечкам памяти. FPM хорошо справляется с этой проблемой, регулируя процессы и их перезапуск.
  • Чем больше процессов вы сделаете, тем больше запросов сможет обработать сервер.
  • FPMможет запускать воркеров в разном окружении и с разными настройками файла php.ini.
  • Если opcode-кэш будет разрушен или повреждён, то FPM сделает экстренную перезагрузку.
  • FPM записывает в логи всё, что происходит на сервере. Благодаря этому вы сможете узнать где возникает ошибка или найти медленно работающий скрипт.

Чистый FPM используется редко, чаще всего применяется связка FPM + NGINX.

Что такое NGINX?

Полное название EngineX –это сервер, разработанный Игорем Сысоевым. Сам автор часто называет своё детище прокси-сервером. NGINX использует протокол HTTPдля работы.

Отличается от Apache и других подобных программ тем, что клиент подключается сначала к прокси-серверу. Этот прокси-сервер передаёт запрос на другую машину, куда изначально хотел попасть клиент. Но это не единственное отличие. NGINX не выполняет тяжёлую работу, поэтому он работает довольно быстро. В основе сервера лежит асинхронно-событийная архитектура.

Конечно же, NGINX не является прокси сервером на самом деле и уж тем более не обеспечивает анонимность работы с программой. Такой название разработчик дал за общий принцип работы прокси и NGINX. Сервер скорее можно назвать конвейером или посредником между запросом пользователя и backend частью программы.

Получая запрос от клиента, NGINX передаёт его FPM-PHP или любой другой библиотеке. Пока FPM занят обработкой переданного ему запроса, NGINX уже работает со следующим пользователем. Такая система не только становится неуязвима к Dosатакам, но начинает работать намного быстрее. Например, NGINX может обрабатывать 1000 и больше запросов в одном процессе.

Точно такая же схема работает с ответами. NGINX получает от backend части ответ и передаёт его пользователю. Получается такой посредник, который быстро перекидывает запросы и ответы от пользователя к серверу.

Также NGINX поддерживает асинхронную работу с файлами. Сегодня скорость чтения и записи файлов с диска достигла больших размеров, поэтому разработчики могут позволить себе обрабатывать файлы в нескольких потоках. Это очень удобно, так как NGINX делит задачу на две части: статичные файлы отправляет на диск, а динамичные запросы отправляет в backend.

Для примера возьмём сервер на Apache, в котором есть 10 процессов, а контента, пусть это будут обычные картинки, у нас 100 штук. В таком случае, пользователю придётся очень долго жать. Пока 10 картинок не обработаются, он не получит следующие 10 и так далее.

Теперь рассмотри такую же ситуацию на NGINX и FPM PHP. У нас по-прежнему остаётся 10 запросов к динамике. Но статичные запросы, а чтение картинки – это статичный запрос, NGINX может обработать самостоятельно, не прибегая к помощи backendчасти. Даже на самой слабой VPSNGINX может работать с 3000 одновременных запросов.

Помимо большой скорости, мы получаем меньший расход оперативной памяти на сервере. Даже голый Apacheбудет потреблять больше ресурсов, чем NGINX и FPMPHP. А вот потребление ресурсов процессора никак не измениться, так как в процессор «засовывают» код на PHP.

Плюсы использования NGINX и FPM PHP

По многим критериям NGINX и FPMPHP выигрывают у Apache.

  • Запросы к статичным объектам обрабатываются в несколько раз быстрее, чем у Apache.
  • Сильно экономиться оперативная память, а значит, экономятся деньги владельца сервера.
  • У NGINX предоставляет много нового функционала, которого нет у Apache.

Однако, все проблемы, которые есть в PHP, останутся с вами. Также в NGINX нет возможности использовать конфигурацию htaccess.

Настройка сервера NGINX и FPM PHP

Перед тем, как настраивать сервер, нужно установить на него CentOS–дистрибутив линукса. Его часто используют при работе с серверами. Также нам понадобится репозиторий EPEL. Чтобы его подключить, используйте команды: # yuminstallepel-release–y.

Теперь обновим все пакеты, которые установлены в системе: # yumupdate–y. После ввода этой команды в терминале появится сообщение, что пакетов не найдено. Так происходит потому, что мы установили чистый дистрибутив.

Устанавливаем NGINX

Установка довольно простая и не займёт много времени. Для начала подключаем репозиторий NGINX:

# rpm -Uvhhttp://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

Цифра «7» после centosозначает версию дистрибутива. Измените цифру, если вы используйте другую версию.

Загружаем пакеты: # yuminstallnginx–y. Если команда выполниться успешно, в терминале появится сообщение «Complete». Теперь запускаем сервер: # systemctlstartnginx, также можно добавить программу в автозагрузку, чтобы сервер стартовал при запуске компьютера: # systemctlstartnginx.

Если вы всё сделали правильно, то при вводе ip-адреса в адресной строке браузера должно появиться приветствие от NGINX. Если этого не произошло, проверьте настройки подключения ещё раз. Проблема может быть скрыта в разрешённых службах или портах. Также проверьте зону Firewalld.

Теперь нужно сделать конфигурационный файл (будем использовать домен build-centos.info):

# mkdir -p /var/www/build-centos.info &&mkdir -p /var/www/build-centos.info/log

Открыть его можно командой: # nano /etc/nginx/conf.d/build-centos.info.conf

В файле нужно прописать настройки для подключения по протоколу https, так как многие SMS системы используют именно этот протокол по умолчанию. Приводить всё содержимое конфигурационного файла здесь не будем, так как он слишком большой. Его код можно найти в интернете.

Установка PHP FPM

Так как в NGINXнет доступа к PHP коду «из коробки», придётся установить FPM отдельно. Для установки будем использовать репозиторий REMI:

# rpm -ivhhttp://rpms.famillecollet.com/enterprise/remi-release-7.rpm

Чтобы сервер работал правильно, найдите и измените файл /etc/yum.repos.d/remi-php74.repo. Значение enabled сделайте равным единице.

Теперь нужно установить FPM: # yuminstallphp-fpm. Эта команда используется для подключения других компонентов. Запускаем сервер и добавляем его в автозагрузку:

# systemctl start php-fpm
# systemctl enable php-fpm

Для проверки сервера вводим команду: # lsof -i:9000. Если всё работает правильно, то в терминале выведется информация о сервере.

PHP FPMдолжен быть запущен через сокет unix. По умолчанию он запускается через адрес 127.0.0.1:9000. Чтобы это исправить, откройте файл /etc/php-fpm.d/www.conf и удалите listen = 127.0.0.1:9000. Вместо него напишите listen = /var/run/php-fpm/php-fpm.sock.

FPM запускается от пользователя apache. Для того чтобы это исправить, в том же файле измените значения user и group на nginx. Теперь перезапустите сервер: # systemctlrestartphp-fpm.

Что такое RoadRunner?

RoadRunner – это сервер для приложений, разработанный компанией SpiralScout. Он появился всего 2 года назад, но уже успел зарекомендовать себя среди разработчиков. Сервер написан на языке Голанг, но прекрасно работает с программами на PHP.

RoadRunner работает по модели load balancer + process manager. Сервер сначала обрабатывает запрос, который поступил от пользователя. Затем, обращается к коду на PHP, предоставляя дальнейшую работу ему.

Серверную часть можно адаптировать под свои задачи. Например, RoadRunner сначала проверит запрос и сообщит об ошибке, если она есть. Таким образом, вы оптимизируете работу своей программы, так как не будете даже запускать код на PHP. Также разработчик может перенести часть кода, требующего много ресурсов, на сервер приложения.

Чем отличается RoadRunner от PHP-FPM+NGINX?

Основное отличие этих серверов в работе с запросами. Связка PHP-FPM+NGINX обеспечивает эффективный менеджер процессов (masterprocess). Менеджер предоставляет воркеров (workerprocess) для обработки запросов, приходящих на сервер. Количество обработчиков постоянно и не меняется со временем.

Воркеры настраиваются отдельно. Каждый из них может обрабатывать определённое количество запросов, но делают они это последовательно, как конвейер. То есть воркер не знает, что у него есть следующий и предыдущий запрос. При каждом новом обращении от клиента обработчик снова начинает загружать базу данных, обращаться к другим ресурсам компьютера, бутстраппить фреймворк и так далее.

Иногда, такая модель эффективна. Например, при «смерти» запроса он не затронет остальные вычисления. Воркер просто загрузит данные для работы и начнёт обрабатывать следующий запрос.

RoadRunner использует другую модель. Воркеры обрабатывают большое количество запросов подряд в цикле. Бутстраппинг происходит только один раз, как и подключение к базе данных. Также разработчик получает возможность перекидывать значение переменных между потоками.

Однако у такого подхода есть и минусы. Коду на PHP часто нужна изоляция для нормальной работы, то есть должны быть зарыты дескрипторы и соединения. В случае с RoadRunner код полностью открыт. Если скрипт вдруг «не умрёт», когда запрос будет выполнен, то возникнет ошибка.

Настройка сервера на RoadRunner

Чтобы собрать сервер, нужно предварительно установить PHP, Голанг и Composer.Сам RoadRunner храниться на GitHub. Чтобы установить его, достаточно скопировать репозиторий:

git clone https://github.com/spiral/roadrunner

Теперь нужно установить зависимости и сам сервер приложений:

cd roadrunner && GO111MODULE=on go mod download
GO111MODULE=on make
GO111MODULE=on make install

Сервер готов к работе. Чтобы протестировать его, создадим одного обработчика. Для этого нужно снова установить зависимости:

composerinit
composerrequirespiral/roadrunner

Теперь опишем работу обработчика. Создаём новый воркер. В этом примере он работает через обычный сокет, но можно использовать протокол TCP.

$worker = new Spiral\RoadRunner\Worker(
new Spiral\Goridge\SocketRelay(“rr.sock”, null, Spiral\Goridge\SocketRelay::SOCK_UNIX)
);
$psr7 = new Spiral\RoadRunner\PSR7Client($worker);

Обрабатываем запрос:

while ($req = $psr7->acceptRequest()) {
try {
$resp = new \Zend\Diactoros\Response();
$resp->getBody()->write(“hello world”);

Обработка ошибок. Если возникнет исключение, нужно закрыть все дескрипторы и соединения.

catch (\Throwable $e) {
$psr7->getWorker()->error((string)$e);
}

Наш воркер готов. Не забудьте перед циклом, в котором обрабатываются запросы, нужно проинициализировать фреймворк, подключиться к БД и так далее. Далее нужно прописать конфигурацию для сервера.

Создаём файл и пишем: # filename: .rr.yaml Далее пишем http, после которого прописываем настройки:

  • Самое важное адрес, на котором будет запущен сервер. Address: :5555.
  • Запускаем обработчик запросов командой: workers:command: “phpworker.php”
  • Указываем как обработчик взаимодействует с сервером (в нашем случае соединение устанавливается через сокет): relay: “unix://rr.sock”
  • Теперь указываем максимальное количество обработчиков и запросов на каждый обработчик: numWorkers: 50 и maxJobs: 200

Конечно, это далеко не все конфигурации, нужные для работы. В реальном проекте конфигурационный файл может состоять из сотни строк. Сервер готов к использованию, осталось только запустить его: rrserve -d –v. После запуска на кран выведется Hellowolrd.

Рекомендации по работе с сервером

Если вы решились перенести свой проект на RoadRunner, обращайте внимание на подключение к базе данных. Лучше создавать новое подключение к БД при каждом запросе либо пристально следить за соединением, чтобы в случае разрыва, откатить транзакцию. Также, в случае потери соединения, нужно закрывать все отрытые файлы.

Утечки памяти – обычное дело для PHP, но, иногда, они становятся слишком существенными. Внимательно следите за кодом, который вы пишете, и подключенными компонентами. Также для борьбы с утечками можно установить значение maxJobs, как в примере выше. Если памяти всё равно расходуется слишком много, очищайте глобальные переменные. Пока обработчик принимает запросы и не вызвана команда dieили exit, никто не будет их очищать.

Переходить на RoadRunner стоит тогда, когда обычных ресурсов NGINX+PHP FPM уже не хватает. Переход не пройдёт бесследно: после подключения сервера приложений ваш код должен быть PSR-7 совместимый. Также у вас не будет возможности использовать большое количество глобальных переменных и сессий.

Скептики часто недоумевают: зачем использовать кашу из GoиPHP, если можно переписать всё приложение сразу на Go, ведь для перехода на RoadRunner придётся приложить много усилий, прежде чем сервер заработает нормально?

Для небольших проектов такое замечание вполне справедливо. Но для больших компаний нецелесообразно увольнять уже сложившуюся команду PHP разработчиков или переучивать их на совершенно другие технологии. Гораздо проще перейти на другой сервер, даже несмотря на то, что он написан на другом языке.

Сравнение FPM и RoadRunner

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

Плюсы и минусы FPM+NGINX

FPM – удобный менеджер процессов, написан на языке С. Многие разработчики используют его в качестве backend части. В отличие от PPM, в FPM не нужно так тщательно следить за расходом оперативной памяти.Также библиотека позволяет легко перенести ранее написанное приложение с чистого PHP на FPM PHP.

Главный минус сервера с FPM в качестве backend части – инициализация глобальных переменных под каждый новый запрос. Кроме переменный, запросы заставляют воркера заново подключаться к базе данных. Также библиотека не позволяет использовать htaccess. Из-за этого некоторым разработчикам приходится придумывать свою реализацию. Те, кто не справляется с проблемой, используют сервера от Apache.

NGINX – сервер, написанный на С. Используется разработчиками в качестве прокси сервера. Он связывает frontend часть иbackend. NGINX позволяет разработчику менять конфигурацию в HTTP через API и запускать одно и тоже приложение с разными настройками. NGINX повышает работоспособность сервера, разделяя запросы на динамические и статические. Динамику прокси-сервер обрабатывает сам, а статику отдаёт коду на PHP.

Связка PHP FPM+NGINX может существенно повысить работоспособность сервера. Но не всегда она бывает эффективна. При большом количестве запросов к серверу может просто не хватить процессов, в таком случае сервер зависнет. Также PHP FPM+NGINX уязвимы к Dosатакам.

Плюсы и минусы RoadRunner

RoadRunner также как NGINX работает по модели прокси сервера. Он получает запросы от frontend и отправляет их PHP коду. Несмотря на то, что сервер написан на языке Go, он прекрасно работает с PHP кодом.

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

Некоторые разработчики упрощают задачу, заставляя воркер на каждый запрос заново подключаться к базе данных и инициализировать переменные. В таком случае не нужно следить за утечками в памяти. Это можно сделать, если установить в коде обработчика флаг —reboot-kernel-after-request.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *