RoadRunner: высокопроизводительный PHP
RoadRunner — это высокопроизводительный сервер приложений PHP, балансировщик нагрузки и менеджер процессов, написанный на Go. Он работает как постоянный процесс, управляющий пулом PHP-воркеров, устраняя накладные расходы на инициализацию PHP-движка и фреймворка приложения при каждом запросе.
Базовая архитектура
Протокол Goridge
RoadRunner использует высокопроизводительный бинарный протокол Goridge для взаимодействия между Go-сервером и PHP-воркерами. Goridge поддерживает различные каналы связи:
- Pipes (стандартный): быстрый, не требует дополнительной настройки.
- TCP Sockets: позволяет PHP-воркерам работать на разных машинах или в контейнерах.
- Unix Sockets: высокопроизводительная локальная связь.
Пул воркеров
RoadRunner поддерживает пул воркеров. Каждый воркер — это отдельный PHP-процесс, который ост аётся живым после обработки запроса. Это означает, что ваше приложение (Laravel, Symfony и т.д.) загружается только один раз.
Конфигурация пула (.rr.yaml)
Ключевые параметры управления жизненным циклом воркеров:
num_workers: количество запускаемых рабочих процессов.max_jobs: количество запросов, которые воркер обрабатывает перед автоматическим завершением и заменой (предотвращает утечки памяти).max_memory: мягкий лимит памяти; воркер заменяется после запроса, если лимит превышен.ttl: максимальное время жизни воркера.idle_ttl: максимальное время простоя воркера.pool.debug: если установлено вtrue, для каждого запроса создаётся новый воркер (полезно при разработке).
Реализация PHP-воркера
Типичный PHP-воркер использует класс Spiral\RoadRunner\Worker. Он работает в бесконечном цикле:
use Spiral\RoadRunner\Worker;
use Nyholm\Psr7\Factory\Psr17Factory;
use Spiral\RoadRunner\Http\HttpWorker;
$worker = Worker::create();
$factory = new Psr17Factory();
$httpWorker = new HttpWorker($worker, $factory, $factory, $factory);
while ($request = $httpWorker->waitRequest()) {
try {
$response = $factory->createResponse(200)->withBody($factory->createStream('Hello RoadRunner!'));
$httpWorker->respond($response);
} catch (\Throwable $e) {
$httpWorker->getWorker()->error((string)$e);
}
}
Ключевые плагины
HTTP Plugin
- Middleware: поддержка middleware на уровне Go (заголовки, сжатие, статические файлы).
- Response Streaming: позволяет отправлять большие ответы клиенту инкрементально.
- SSL/TLS: встроенная поддержка HTTPS и HTTP/2.
Key-Value (KV) Plugin
Предоставляет унифицированный интерфейс для кэширования и управления состоянием между воркерами.
- Драйверы:
redis,memcached,boltdb(файл),memory.
Jobs (Queues) Plugin
Централизованное потребление и управление задачами в рамках Go-процесса.
- Драйверы:
amqp,beanstalk,redis,sqs,nats,boltdb,memory.
Service Plugin
Позволяет запускать любой бинарный файл или скрипт как «sidecar»-процесс (например, пользовательский Go-демон или Python-скрипт) и следить за его работоспособностью.
Locks Plugin
Предоставляет распределённые блокировки для синхронизации доступа к общим ресурсам между несколькими воркерами или экземплярами RoadRunner.
Лучшие практики для долгоживущего PHP
1. Управление памятью
PHP изначально не был предназначен для долгоживущих процессов. Даже если ваш код чист, сторонние библиотеки могут допускать утечки памяти. Всегда устанавливайте max_jobs или max_memory в конфигурации пула.
2. Сброс состояния
Статические переменные и экземпляры-одиночки (например, в Service Container Laravel) сохраняются между запросами. Необходимо вручную сбрасывать или перепривязывать сервисы, хранящие данные, специфичные для запроса.
3. Подключения к базе данных
Соединения могут разрываться по тайм-ауту, если долго не используются. Убедитесь, что ваш клиент БД поддерживает переподключение, или используйте настройку ttl RoadRunner для обновления воркеров.
4. Буферизация вывода
Избегайте прямого использования echo или print — они могут повредить бинарный протокол. Используйте объекты ответов PSR-7. RoadRunner 2.0+ автоматически перенаправляет STDOUT в STDERR для смягчения этой проблемы.
Мониторинг и проверки работоспособности
Плагин status предоставляет возможности мониторинга:
/health: проверка жизнеспособности (работает ли сервер RR?)./ready: проверка готовности (есть ли хотя бы один свободный воркер для обработки запросов?).
Обычно интегрируются с Kubernetes или другими оркестраторами для автоматического масштабирования и управления состоянием.
Интеграция с Temporal
RoadRunner является основным PHP-воркером для Temporal — движка оркестрации с открытым исходным кодом для состояний и длительных рабочих процессов. Это позволяет строить сложные распределённые системы на стандартной логике PHP.