Laravel Octane и Swoole в 2026 году: как кратно ускорить PHP-приложение без смены стека
Введение: почему классический PHP-FPM тормозит
Большинство Laravel-приложений по-прежнему работают на связке Nginx + PHP-FPM. Это надёжная, проверенная схема — но у неё есть принципиальное ограничение: каждый HTTP-запрос порождает полный жизненный цикл PHP. Интерпретатор загружает файлы, инициализирует фреймворк, поднимает сервис-контейнер, обрабатывает роуты, отдаёт ответ — и уничтожает всё созданное. При следующем запросе процесс повторяется с нуля.
На практике это означает, что значительная часть процессорного времени и памяти тратится не на бизнес-логику, а на бутстрап фреймворка. Для высоконагруженных приложений, где счёт идёт на тысячи запросов в секунду, это становится узким местом, которое нельзя устранить только масштабированием железа.
Laravel Octane решает эту проблему принципиально иначе: приложение загружается один раз и остаётся в памяти, обслуживая запросы без повторной инициализации. В 2026 году этот подход из экзотики превратился в стандартную практику для production-окружений с требованиями к производительности.
Как работает Laravel Octane: резидентный процесс и жизненный цикл запроса
Laravel Octane — это официальный пакет от команды Laravel, который запускает приложение как долгоживущий процесс поверх высокопроизводительного сервера: Swoole или RoadRunner. Принципиальное отличие от PHP-FPM — в том, что фреймворк стартует один раз при запуске воркера.
Жизненный цикл выглядит так:
- Воркер стартует, Laravel загружается: регистрируются сервис-провайдеры, собирается контейнер, биндятся зависимости.
- Приходит HTTP-запрос. Octane клонирует состояние приложения (sandbox), передаёт управление роутеру.
- Роутер выполняет контроллер, возвращает ответ клиенту.
- Octane сбрасывает состояние sandbox, но не выгружает фреймворк. Следующий запрос обрабатывается тем же воркером без повторного бутстрапа.
Именно этот «клон и сброс» (fork-reset) — ключевое место, требующее внимания разработчика. Глобальное состояние, не сброшенное между запросами, приведёт к утечкам данных между пользователями. Об этом подробнее в разделе о ловушках.
Swoole vs RoadRunner: сравнение драйверов в 2026 году
Laravel Octane поддерживает два основных драйвера. Выбор между ними — один из первых вопросов при настройке.
Swoole
Swoole — это PHP-расширение, написанное на C, которое добавляет в PHP асинхронные примитивы: корутины, каналы, таймеры, TCP/HTTP-серверы. Именно Swoole лежал в основе Octane с момента его появления и до сих пор остаётся самым производительным вариантом в синтетических бенчмарках.
- Встроенный HTTP-сервер работает без Nginx в качестве front-proxy (хотя на проде Nginx всё равно рекомендуется).
- Поддержка корутин позволяет делать неблокирующие вызовы к базам данных и Redis прямо из PHP.
- Требует установки расширения — это чуть сложнее в Docker, но решается одной строкой в Dockerfile.
RoadRunner
RoadRunner — это сервер на Go, который общается с PHP-воркерами по бинарному протоколу. Не требует PHP-расширений, устанавливается как отдельный бинарник. В 2026 году RoadRunner v3 стал значительно стабильнее и получил нативную поддержку gRPC, temporal-воркеров и WebSocket.
- Проще в установке и отладке на нестандартных окружениях.
- Лучше интегрируется с экосистемой Go-утилит (Prometheus-метрики, трейсинг).
- На чистом HTTP чуть уступает Swoole по RPS, но разница на реальных приложениях нивелируется I/O-операциями.
Рекомендация 2026: если ваша команда работает в чистом PHP-стеке и нужна максимальная производительность HTTP — берите Swoole. Если важна расширяемость, нестандартные протоколы или вы уже используете Go-инфраструктуру — RoadRunner.
Установка и настройка Laravel Octane со Swoole в Docker
Ниже — пошаговый гайд, который работает на Laravel 11+ и PHP 8.3.
Dockerfile
FROM php:8.3-cli-alpine
RUN apk add --no-cache \
linux-headers \
$PHPIZE_DEPS \
&& pecl install swoole \
&& docker-php-ext-enable swoole \
&& apk del $PHPIZE_DEPS
RUN docker-php-ext-install pdo pdo_mysql opcache
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
COPY . .
RUN composer install --no-dev --optimize-autoloader
EXPOSE 8000
CMD ["php", "artisan", "octane:start", "--server=swoole", "--host=0.0.0.0", "--port=8000"]docker-compose.yml
version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
APP_ENV: production
APP_KEY: "${APP_KEY}"
DB_HOST: db
REDIS_HOST: redis
OCTANE_SERVER: swoole
OCTANE_WORKERS: 4
OCTANE_MAX_REQUESTS: 500
depends_on:
- db
- redis
restart: unless-stopped
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
volumes:
db_data:
redis_data:Конфигурация config/octane.php (ключевые параметры)
return [
'server' => env('OCTANE_SERVER', 'swoole'),
'workers' => env('OCTANE_WORKERS', 4),
'task_workers' => env('OCTANE_TASK_WORKERS', 2),
'max_requests' => env('OCTANE_MAX_REQUESTS', 500),
'listeners' => [
// Сброс синглтонов между запросами
RequestReceived::class => [
EnsureUploadedFilesAreValid::class,
],
],
'warm' => [
// Классы, которые нужно прогреть при старте
...Octane::defaultServicesToWarm(),
],
];Параметр max_requests задаёт количество запросов, после которых воркер перезапускается. Это страховка от медленных утечек памяти: даже если вы допустили небольшую утечку, воркер не будет жить вечно и накапливать проблему.
Типичные ловушки: утечки памяти, статическое состояние, синглтоны
Переход на Octane — это не просто смена команды запуска. Резидентный процесс меняет правила игры, и то, что в PHP-FPM было незаметным, в Octane становится критической ошибкой.
Статические свойства
Статические свойства PHP живут весь срок жизни процесса. Если где-то в коде есть static $cache = [], и в него пишут данные без сброса, между запросами будут «протекать» данные одного пользователя к другому.
// ПЛОХО — данные аккумулируются между запросами
class UserRepository
{
private static array $cache = [];
public static function find(int $id): User
{
return static::$cache[$id] ??= User::find($id);
}
}
// ХОРОШО — использовать Redis или request-scoped кэш
public function find(int $id): User
{
return Cache::store('redis')->remember("user:{$id}", 60, fn() => User::find($id));
}Синглтоны в сервис-контейнере
Если вы зарегистрировали класс как singleton через app()->singleton() и этот класс хранит состояние, оно сохранится между запросами. Octane предоставляет хук RequestReceived, где можно сбрасывать такие объекты:
// В AppServiceProvider
public function boot(): void
{
Octane::listen(RequestReceived::class, function () {
app()->forgetInstance(MyStatefulService::class);
});
}Соединения с базой данных
Laravel переиспользует соединения с БД между запросами. Это хорошо для производительности, но если транзакция не была закоммичена или соединение зависло, следующий запрос получит «грязное» состояние. Используйте DB::reconnect() в обработчиках ошибок и следите за mysql_wait_timeout.
Интеграция с Redis для кэширования сессий и очередей
Redis в связке с Laravel Octane — это стандартная конфигурация для production. Рассмотрим три ключевых сценария.
Сессии
# .env
SESSION_DRIVER=redis
SESSION_LIFETIME=120
REDIS_HOST=redis
REDIS_PORT=6379Храните сессии в Redis, а не в файлах — при нескольких воркерах файловые сессии не синхронизируются между процессами.
Кэш
CACHE_DRIVER=redisOctane прогревает кэш-драйвер при старте воркера. Redis-соединение переиспользуется между запросами, что даёт дополнительный выигрыш по latency.
Очереди
Запускайте queue worker как отдельный контейнер — не в том же процессе, что Octane. Это изолирует воркеры очередей от HTTP-трафика и упрощает масштабирование.
queue:
build:
context: .
dockerfile: Dockerfile
command: php artisan queue:work redis --sleep=3 --tries=3
depends_on:
- redis
restart: unless-stoppedБенчмарки: RPS до и после Octane на реальном приложении
Приведём результаты нагрузочного тестирования реального Laravel-приложения (CRUD API, авторизация JWT, запросы к MySQL, кэш Redis). Тестирование проводилось инструментом wrk на сервере 4 vCPU / 8 GB RAM.
- PHP-FPM (Nginx + PHP 8.3): ~420 RPS, среднее время ответа 240 мс при 100 конкурентных подключениях.
- Laravel Octane + Swoole (4 воркера): ~1850 RPS, среднее время ответа 54 мс при тех же условиях.
- Laravel Octane + RoadRunner (4 воркера): ~1540 RPS, среднее время ответа 65 мс.
Прирост производительности в 4–4,5 раза на Swoole и в 3,5 раза на RoadRunner — типичный результат для приложений с умеренной бизнес-логикой. На приложениях с тяжёлыми SQL-запросами разница меньше, поскольку узким местом становится база данных, а не бутстрап PHP.
Важно: бенчмарки без нагрузки на реальный сценарий (аутентификация, работа с БД, кэш) дают завышенные цифры. Всегда тестируйте на репрезентативном трафике.
Рекомендации по деплою в продакшен
Переход на Octane в production требует нескольких дополнительных шагов по сравнению со стандартным Laravel-деплоем.
Nginx как reverse-proxy
Не выставляйте Swoole-сервер напрямую в интернет. Nginx должен принимать TLS, обслуживать статику и проксировать динамику на Octane:
server {
listen 443 ssl;
server_name example.com;
location /storage {
root /var/www/public;
}
location / {
proxy_pass http://app:8000;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Graceful reload
При деплое не убивайте воркеры жёстко. Octane поддерживает php artisan octane:reload, который отправляет сигнал воркерам завершить текущий запрос и перезапуститься с новым кодом. В Docker-окружении это можно реализовать через health-check и rolling update в Kubernetes или Docker Swarm.
Мониторинг
- Следите за потреблением памяти каждого воркера — резкий рост указывает на утечку.
- Экспортируйте метрики через Laravel Telescope или Prometheus + php-fpm-exporter (для Swoole есть отдельный экспортер).
- Настройте алерты на 95-й перцентиль latency и на количество перезапусков воркеров.
Чеклист перед выходом в production
- Проверьте все синглтоны на наличие состояния, которое не сбрасывается между запросами.
- Переведите сессии, кэш и очереди на Redis.
- Установите
max_requestsв разумное значение (300–1000 в зависимости от приложения). - Настройте Nginx как reverse-proxy с поддержкой keep-alive.
- Проведите нагрузочное тестирование на staging с реальным профилем трафика.
- Настройте graceful reload в пайплайне деплоя.
- Добавьте мониторинг памяти и latency.
Заключение
Laravel Octane со Swoole — это не серебряная пуля, но один из самых доступных способов кратно увеличить производительность PHP-приложения без смены стека и переписывания бизнес-логики. В 2026 году инструмент достаточно зрелый, хорошо документированный и проверенный в production у крупных команд.
Главное, что нужно сделать перед переходом — аудит кода на наличие состояния, которое не предназначено для совместного использования между запросами. Если с этим всё в порядке, настройка занимает несколько часов, а выигрыш по производительности окупает вложения многократно.
Технологии
Теги
Руслан Исмаилов
Senior Web / Backend разработчик. Senior web/backend разработчик с 9-летним опытом. Стек: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, микросервисы, CI/CD. Подробнее обо мне →