24. Долгоживущие процессы (RoadRunner)
Что такое RoadRunner и как он работает?
MiddleОтвет: RoadRunner — это высокопроизводительный сервер PHP-приложений, балансировщик нагрузки и менеджер процессов, написанный на Go. Он работает как постоянный процесс, управляющий пулом PHP-воркеров. Когда приходит запрос, RoadRunner передаёт его свободному PHP-воркеру через высокопроизводительный бинарный протокол (Goridge). PHP-воркер продолжает жить после завершения запроса, что исключает накладные расходы на повторную ини циализацию PHP-движка и фреймворка приложения (bootstrapping) при каждом запросе.
Подробное руководство по RoadRunner

Что такое PHP-воркер в контексте RoadRunner?
MiddleОтвет: PHP-воркер — это скрипт, работающий в непрерывном цикле. Он использует класс Spiral\RoadRunner\Worker для ожидания запросов от сервера RoadRunner, их обработки (часто через PSR-7) и отправки ответов. Воркеры могут взаимодействовать с сервером через стандартные каналы ввода-вывода (по умолчанию), TCP или Unix-сокеты. Начиная с RoadRunner 2.0, любые предупреждения или вывод в STDOUT автоматически перенаправляются в STDERR для предотвращения повреждения протокола.
Как RoadRunner управляет пулом воркеров?
MiddleОтвет: RoadRunner поддерживает пул PHP-воркеров и может динамически масштабировать их количество. Он использует стратегию супервизии для перезапуска воркеров на основе различных лимитов, заданных в .rr.yaml:
max_jobs: Количество запросов, которое воркер может обработать до перезапуска.max_memory: Лимит памяти на один воркер.ttl: Максимальное время жизни воркера.idle_ttl: Максимальное время простоя воркера. Для локальной разработки можно использоватьpool.debug = true, чтобы воркер выделялся только при поступлении запроса, что упрощает отладку.
Что нужно учитывать разработчику при написании кода для долгоживущего PHP-окружения?
MiddleОтвет:
- Утечки памяти: Любая утечённая память будет накапливаться со временем; используйте
supervisor.max_worker_memoryкак предохранитель. - Сохранение состояния: Статические переменные и глобальное состояние сохраняются между запросами, что может приводить к утечке данных или непредсказуемому поведению, если их не сбрасывать.
- Управление ресурсами: Соединения с базой данных и файловые дескрипторы следует повторно проверять или корректно закрывать, так как они могут устареть или оставаться открытыми на протяжении множества запросов.
- Обработка ошибок: Необработанные исключения могут привести к аварийному завершению воркера; их нужно перехватывать и сообщать RoadRunner через
$worker->error().
Что такое плагин Key-Value (KV) в RoadRunner?
MiddleОтвет: Плагин KV предоставляет единый интерфейс для работы с различными хранилищами для простого хранения данных по ключам. Он выносит кеширование или управление состоянием из PHP на сервер Go. Поддерживаемые драйверы:
redis(распределённый)memcached(распределённый)boltdb(файловый)memory(быстрый, локальный для экземпляра RR)
Как работают очереди и задачи (Jobs) в RoadRunner?
MiddleОтвет: RoadRunner выступает как потребитель и менеджер задач, получая задания от ра зличных брокеров и передавая их PHP-воркерам. Это централизует управление задачами без необходимости запуска отдельных CLI-процессов. Поддерживаемые драйверы/брокеры:
amqp,beanstalk,redis,sqs,nats,boltdbиmemory.
Как RoadRunner обрабатывает HTTP-запросы и заголовки?
MiddleОтвет: HTTP-плагин RoadRunner работает как быстрый веб-сервер, преобразующий входящие запросы в PSR-7-совместимые объекты для PHP-воркеров. Он поддерживает сжатие Gzip, пользовательские заголовки и middleware на уровне Go. Также поддерживается потоковая передача ответов, позволяющая PHP отправлять клиенту большие объёмы данных инкрементально.
Что такое плагин Centrifuge в RoadRunner?
SeniorОтвет: Плагин Centrifuge интегрирует RoadRunner с Centrifugo или его Go-аналогом, обеспечивая обмен сообщениями в реальном времени (WebSockets, SockJS) в PHP-приложениях. RoadRunner обрабатывает тысячи постоянных соединений на уровне Go, в то время как PHP-воркеры занимаются только бизнес-логикой и обработкой событий.
Для чего предназначен плагин Service?
SeniorОтвет: Плагин Service позволяет RoadRunner запускать и контролировать любой бинарный файл или скрипт как дочерний процесс (sidecar). Он гарантирует, что процесс всегда работает, автоматически перезапуская его в случае сбоя. Это идеально подходит для фоновых задач: ко нсьюмеров, экспортёров метрик или прокси-серверов.
Как работает плагин Locks?
SeniorОтвет: Плагин Locks предоставляет механизм распределённых блокировок. Он позволяет PHP-воркерам синхронизировать доступ к общим ресурсам между несколькими воркерами или даже несколькими экземплярами RoadRunner с помощью бэкендов, таких как Redis или локальная память.
Какие лучшие практики запуска RoadRunner в продакшене?
SeniorОтвет:
- Супервизия процессов: Использовать
systemdилиsupervisordдля поддержания работы осно вного процесса RoadRunner. - Лимиты воркеров: Всегда устанавливать
max_jobsилиmax_memoryдля предотвращения чрезмерного потребления памяти. - Мониторинг состояния: Использовать плагин
statusдля проверок работоспособности и готовности. - Конфигурация ОС: Увеличить количество допустимых файловых дескрипторов (
ulimit -n). - Логирование: Настроить структурированное логирование (JSON) для удобного потребления инструментами управления логами.
Что такое потоковая передача ответов и проверки состояния в RoadRunner?
SeniorОтвет:
- Потоковая передача ответов (Response Streaming): Позволяет PHP отправлять данные клиенту инкрементально, снижая потребление памяти при скачивании больших файлов или передаче данных в реальном времени.
- Проверки состояния (Health Checks): Плагин
statusпредоставляет эндпоинты/health(работает ли сервер?) и/ready(есть ли хотя бы один свободный воркер?). Они необходимы для liveness/readiness-проб в Kubernetes или проверок состояния балансировщика нагрузки.
Как RoadRunner интегрируется с Temporal?
SeniorОтвет: RoadRunner может выступать воркером для Temporal — движка оркестрации сложных, stateful и долгоживущих рабочих процессов (workflow). PHP-разработчики могут писать логику workflow и activity на PHP, а RoadRunner обеспечивает взаимодействие с сервером Temporal через протокол Goridge.