Привет.
Много раз уже слышал о RoadRunner - сервер веб-приложений, написанный на Go. Думаю, настало время пощупать, что это такое.
PHP работает по простому принципу - один запрос - один процесс. Мы открываем страницу - на сервер уходит запрос. Где-то на сервере есть стек с горячими PHP-FPM процессами, один из которых выделяется и обрабатывает пришедший запрос. Отдав ответ - процесс выгружает все данные из памяти, очищает своё состояние и умирает. Это, я думаю, одна из вещей, почему многие не любят PHP. И правда, при растущих нагрузках рост процессов - неприятный удар по производительности, часто требующий пересмотра архитектуры, масштабирования и редкий поглядываний в сторону потоков, когда разработчик внезапно узнаёт, что они есть в PHP.
Как правило, в сторону потоков мы смотрим недолго. Потоки появились не так давно, и, как нас уверяет php.net - стабильно работают в PHP 7.2. У меня был опыт реализации многопоточной системы, где почему-то на PHP я решил разрулить проблемы с множественной обработкой большого числа запросов. Первое, что неприятно ударило по разработке - пересборка PHP с флагом ZTS - чтобы многопоточка заработала в принципе. Второе - это далеко не все библиотеки поддреживают многопоточный режим, и, если одна из либ его не поддерживает - мы обламываемся.
Недавно я наткнулся на статью - Разработка гибридных PHP/Go приложений с использованием RoadRunner. Если коротко - ребята написали сервер, который имеет интеграцию с большинством PHP-фреймворков. Этот сервер поднимает несколько PHP-процессов, в которые уже инициализированы все библиотеки и весь исполняющий код. Эти процессы держаться в памяти, в неком вечном цикле. Все входящие запросы сервер ловит в где-то снаружи, вне наших PHP-процессов, а затем отправляет данные на обработку в PHP-процессы, которые, после обработки, не умирают. Обработав результат, сервер забирает данные и отдаёт клиенту, а процесс продолжает жить. Весь контроль памяти и балансировка процессов - на плечах сервера, и справляется с ней он, судя по отзывам, неплохо.
Мы любим графики и сравнения, поэтому приведу сравнение из этой статьи:
Звучит как музыка, поэтому я решил, что мы должны это попробовать.
Создадим новый проект:
symfony new rrt --full
cd rrt
Устанавливаем roadrunner:
composer req spiral/roadrunner symfony/psr-http-message-bridge
Теперь в bin
создаём файл worker.php
, который будет поднимать воркер, обрабатывающий запросы: