К основному содержимому

Swoole и RoadRunner: PHP как долгоживущий процесс

PHP · 29.09.2026

Классический PHP-FPM запускает интерпретатор заново на каждый запрос: поднял приложение, обработал один запрос, выгрузил всё из памяти. Swoole и RoadRunner работают иначе — приложение загружается один раз и держится в памяти между запросами, как в Node.js или Go. Это ускоряет обработку в разы, но требует другого подхода к коду.

Чем это отличается от привычного PHP-FPM

В модели FPM каждый запрос получает чистое состояние: никаких утечек между пользователями, но каждый раз заново инициализируется контейнер зависимостей, подключение к базе и автозагрузка классов. В модели Swoole или RoadRunner инициализация происходит один раз при старте воркера, а дальше на каждый запрос выполняется только код обработчика — это и даёт основной прирост скорости. Разницу с обычным CLI-запуском PHP разбирали в статье про PHP CLI и FPM.

Обратная сторона — глобальное состояние. Статические свойства классов, синглтоны и просто забытые переменные в замыканиях живут между запросами и могут утекать в память или протекать данными одного пользователя к другому, если код не написан с расчётом на долгий процесс.

Установка Swoole как PHP-расширения

sudo apt install php8.3-dev php-pear
sudo pecl install swoole
echo "extension=swoole.so" | sudo tee /etc/php/8.3/mods-available/swoole.ini
sudo phpenmod swoole
php -m | grep swoole

Swoole встраивается прямо в PHP как расширение и добавляет классы для асинхронного HTTP-сервера, корутин и вебсокетов. Про отдельный протокол вебсокетов на чистом PHP — в статье про WebSockets с Ratchet.

RoadRunner как альтернатива

RoadRunner устроен иначе: это отдельный бинарник на Go, который держит пул PHP-воркеров и общается с ними по протоколу Goridge через stdin/stdout. PHP-код при этом остаётся обычным PHP без специального расширения — нужен только пакет spiral/roadrunner-http через Composer, который описан в статье про установку Composer.

ПараметрSwooleRoadRunner
Типрасширение PHPотдельный бинарник на Go
Корутиныда, встроенынет, воркеры однопоточные
Совместимость с Laravel/Symfonyчерез отдельные пакетычерез отдельные пакеты
Порог входавышениже

На что смотреть при утечках памяти

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

  • Статические массивы и кэши уровня класса, которые растут с каждым запросом и никогда не очищаются.
  • Подключение к базе данных, которое переоткрывается на каждый запрос вместо переиспользования уже открытого соединения.
  • Глобальный контейнер зависимостей — если он создаётся заново на каждый запрос, то теряется весь смысл долгоживущего процесса.
  • Циклические ссылки между объектами, которые сборщик мусора PHP не всегда убирает вовремя в длинном процессе.

Мониторинг воркеров и перезапуск

Даже правильно написанное приложение стоит перезапускать по расписанию, как и обычные очереди — подход почти такой же, как в статье про Supervisor для очередей. У Swoole есть встроенный параметр max_request, который перезапускает воркер после заданного числа обработанных запросов:

$server->set([
    'worker_num' => 4,
    'max_request' => 5000,
    'task_worker_num' => 2,
]);

Чек-лист перехода на долгоживущий процесс

  1. Уберите из кода любые статические свойства, которые накапливают данные между запросами без явной очистки.
  2. Настройте плановый перезапуск воркеров через max_request в Swoole или аналогичный лимит в RoadRunner.
  3. Прогоните нагрузочное тестирование перед переключением прода — рост задержек по времени работы воркера сразу покажет утечку.
← Назад в базу знаний Задать вопрос поддержке