Backend-разработка

Laravel Reverb в 2026 году: WebSocket-сервер на PHP без Node.js и сторонних сервисов

Ruslan Ismailov Опубликовано 12 мин чтения
L

Введение: проблема realtime в PHP-приложениях

Долгое время PHP считался языком «запрос-ответ»: пришёл HTTP-запрос — отдали ответ. Реализовать что-то в реальном времени означало либо тащить в стек Node.js, либо платить за Pusher или Ably, либо возиться с self-hosted Soketi. Каждый из этих путей добавлял сложность: другой рантайм, новый сервис, дополнительные расходы или нестабильная самостоятельная поддержка.

История решений выглядела примерно так:

  • Pusher — удобно, но платно и данные уходят на сторонний сервер.
  • Socket.io + Node.js — мощно, но теперь в проекте два рантайма.
  • Soketi — self-hosted Pusher-совместимый сервер на Node.js. Лучше, но всё равно Node.
  • Ably — облачный вариант с более щедрым бесплатным планом, но та же зависимость от третьей стороны.

В марте 2024 года команда Laravel представила Laravel Reverb — первый официальный WebSocket-сервер, написанный на чистом PHP и встроенный прямо в экосистему фреймворка. В 2026 году это уже зрелое, production-ready решение. Давайте разберёмся, как оно устроено и как его использовать.

Что такое Laravel Reverb и как он появился

Laravel Reverb — это WebSocket-сервер первого класса для Laravel, реализованный поверх библиотеки ReactPHP. Он полностью совместим с протоколом Pusher Channels, а значит, фронтенд-код, который работал с Pusher или Soketi, переключается на Reverb без изменений — просто меняешь credentials в конфиге.

Reverb появился как ответ на один из самых популярных запросов сообщества: дать разработчикам на Laravel возможность строить realtime-приложения без выхода за пределы PHP-экосистемы. Джо Диксон (Joe Dixon) и команда Laravel потратили несколько месяцев на построение асинхронного event-loop поверх ReactPHP, который позволяет PHP держать тысячи открытых WebSocket-соединений в рамках одного долгоживущего процесса.

«Reverb создан, чтобы Laravel-разработчики могли строить realtime-приложения так же просто, как они строят обычные HTTP-эндпоинты.» — команда Laravel

Архитектура: как Reverb работает внутри

Понять архитектуру Reverb важно, чтобы правильно его настроить и не удивляться поведению в продакшене.

Event Loop и ReactPHP

Reverb запускается как долгоживущий PHP-процесс (не умирает после каждого запроса). Внутри — event loop на базе ReactPHP, который принимает входящие WebSocket-соединения и обрабатывает сообщения асинхронно. Это принципиально отличается от стандартной модели PHP-FPM.

Связь с Broadcasting и Event

Laravel Broadcasting — это абстракция над транспортом событий. Когда вы вызываете broadcast(new OrderShipped($order)), Laravel Broadcasting решает, куда отправить событие: в Pusher, в Redis, в Reverb или куда-то ещё. Reverb регистрируется как broadcasting-драйвер reverb.

Цепочка выглядит так:

  1. PHP-код файрит событие через broadcast().
  2. Laravel Broadcasting отправляет его в очередь (или напрямую) в Reverb-сервер по HTTP/WebSocket.
  3. Reverb рассылает сообщение всем подписанным клиентам по нужным каналам.
  4. Фронтенд получает событие через laravel-echo и Pusher JS SDK.

Установка и базовая настройка Reverb

Давайте пройдём установку шаг за шагом. Предполагается, что у вас уже есть Laravel-проект версии 11+.

Установка пакета

composer require laravel/reverb
php artisan reverb:install

Команда reverb:install опубликует конфиг config/reverb.php, добавит нужные переменные в .env и настроит Broadcasting на драйвер reverb.

Настройка .env

BROADCAST_DRIVER=reverb

REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret
REVERB_HOST=0.0.0.0
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="localhost"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"

Запуск сервера

php artisan reverb:start
# или с указанием хоста и порта
php artisan reverb:start --host=0.0.0.0 --port=8080

Настройка фронтенда

Установите зависимости:

npm install --save-dev laravel-echo pusher-js

Настройте Echo в resources/js/bootstrap.js:

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'reverb',
    key: import.meta.env.VITE_REVERB_APP_KEY,
    wsHost: import.meta.env.VITE_REVERB_HOST,
    wsPort: import.meta.env.VITE_REVERB_PORT,
    wssPort: import.meta.env.VITE_REVERB_PORT,
    forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});

Масштабирование Reverb с Redis

Один инстанс Reverb — отлично для старта, но что делать, когда нагрузка растёт и нужно несколько серверов? Здесь на помощь приходит Redis.

Reverb поддерживает Redis как pub/sub-бэкенд. Когда событие публикуется на одном инстансе Reverb, Redis рассылает его всем остальным инстансам, и те доставляют сообщение своим подключённым клиентам. Это классическая схема горизонтального масштабирования.

Настройка Redis-бэкенда

# .env
REVERB_SCALING_ENABLED=true
REVERB_SCALING_DRIVER=redis

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

В config/reverb.php убедитесь, что секция scaling выглядит так:

'scaling' => [
    'enabled' => env('REVERB_SCALING_ENABLED', false),
    'channel' => 'reverb',
    'server' => [
        'url' => env('REDIS_URL'),
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => env('REVERB_SCALING_REDIS_DATABASE', '0'),
    ],
],

Теперь можно запускать несколько инстансов php artisan reverb:start за балансировщиком нагрузки, и Redis будет синхронизировать состояние между ними.

Деплой Reverb в Docker и Kubernetes

Docker-конфигурация

Пример Dockerfile для Laravel-приложения с Reverb:

FROM php:8.3-cli-alpine

RUN apk add --no-cache \
    git curl unzip libzip-dev \
    && docker-php-ext-install zip pcntl sockets

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /app
COPY . .

RUN composer install --no-dev --optimize-autoloader

EXPOSE 8080

CMD ["php", "artisan", "reverb:start", "--host=0.0.0.0", "--port=8080"]

Пример docker-compose.yml:

version: '3.9'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - APP_ENV=production
      - REVERB_APP_ID=my-app-id
      - REVERB_APP_KEY=my-app-key
      - REVERB_APP_SECRET=my-app-secret
      - REVERB_SCALING_ENABLED=true
      - REDIS_HOST=redis
    depends_on:
      - redis

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

Kubernetes: Deployment и Service

В Kubernetes Reverb-сервер деплоится как отдельный Deployment с несколькими репликами. Трафик WebSocket прокидывается через Service типа LoadBalancer или через Ingress с поддержкой WebSocket.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: reverb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: reverb
  template:
    metadata:
      labels:
        app: reverb
    spec:
      containers:
        - name: reverb
          image: your-registry/laravel-app:latest
          command: ["php", "artisan", "reverb:start", "--host=0.0.0.0", "--port=8080"]
          ports:
            - containerPort: 8080
          env:
            - name: REVERB_SCALING_ENABLED
              value: "true"
            - name: REDIS_HOST
              value: redis-service
---
apiVersion: v1
kind: Service
metadata:
  name: reverb-service
spec:
  selector:
    app: reverb
  ports:
    - port: 8080
      targetPort: 8080
  type: LoadBalancer

Важно: убедитесь, что ваш Ingress-контроллер (например, nginx-ingress) настроен на поддержку апгрейда соединений до WebSocket через заголовки Upgrade и Connection.

Практический пример: чат в реальном времени

Создадим простой публичный чат с использованием Laravel Broadcasting и Vue 3.

Событие на сервере

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;

class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets;

    public function __construct(
        public string $message,
        public string $username
    ) {}

    public function broadcastOn(): Channel
    {
        return new Channel('public-chat');
    }

    public function broadcastAs(): string
    {
        return 'message.sent';
    }
}

Контроллер

<?php

namespace App\Http\Controllers;

use App\Events\MessageSent;
use Illuminate\Http\Request;

class ChatController extends Controller
{
    public function send(Request $request)
    {
        $request->validate(['message' => 'required|string|max:500']);

        broadcast(new MessageSent(
            message: $request->message,
            username: $request->user()->name ?? 'Anonymous'
        ));

        return response()->json(['status' => 'sent']);
    }
}

Vue-компонент

<script setup>
import { ref, onMounted } from 'vue';

const messages = ref([]);
const newMessage = ref('');

onMounted(() => {
    window.Echo.channel('public-chat')
        .listen('.message.sent', (event) => {
            messages.value.push(event);
        });
});

const sendMessage = async () => {
    await fetch('/chat/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content },
        body: JSON.stringify({ message: newMessage.value })
    });
    newMessage.value = '';
};
</script>

<template>
  <div>
    <div v-for="msg in messages" :key="msg.message">
      <strong>{{ msg.username }}:</strong> {{ msg.message }}
    </div>
    <input v-model="newMessage" @keyup.enter="sendMessage" placeholder="Введите сообщение..." />
  </div>
</template>

Сравнение Reverb с Soketi и Pusher в 2026 году

Выбор инструмента зависит от ваших требований. Вот как выглядит картина в 2026 году:

  • Laravel Reverb — нативный PHP, zero external runtime, бесплатно, отличная интеграция с Laravel Broadcasting, поддержка Redis для масштабирования. Идеален для команд, работающих в PHP-стеке. В 2026 году стабилен и поддерживается командой Laravel.
  • Soketi — self-hosted, Node.js, Pusher-совместимый. Хорошо работает, но требует Node.js. Развитие замедлилось после появления Reverb, сообщество частично мигрировало.
  • Pusher — облачный, zero maintenance, щедрый бесплатный план (200 одновременных соединений). Выбор для стартапов и MVP, где не хочется думать об инфраструктуре. Минус — данные уходят на чужой сервер, есть лимиты и цена при росте.
  • Ably — более продвинутый облачный сервис с гарантиями доставки, историей сообщений и глобальной сетью. Дороже Pusher при масштабировании, зато больше возможностей.

Вывод: если вы работаете в Laravel-стеке и хотите полный контроль над инфраструктурой — Reverb это ваш выбор в 2026 году.

Ограничения и когда стоит выбрать другой инструмент

Reverb — отличный инструмент, но у него есть ограничения, о которых нужно знать:

  • Один поток на процесс. PHP — не Go и не Erlang. Несмотря на event loop, Reverb работает в одном потоке. Для экстремальных нагрузок (сотни тысяч одновременных соединений) потребуется тщательная настройка горизонтального масштабирования с Redis.
  • Нет встроенной истории сообщений. Reverb не хранит историю. Если нужна доставка пропущенных сообщений — реализуйте это сами через базу данных или выбирайте Ably.
  • Нет presence-каналов out of the box. Точнее, presence-каналы поддерживаются, но их состояние не сохраняется между рестартами сервера без Redis.
  • WebSocket-only. Reverb не поддерживает SSE (Server-Sent Events) или Long Polling как фолбэк. Если нужна поддержка окружений без WebSocket — Laravel Echo с другим транспортом или Mercure будут лучшим выбором.
  • Production-нагрузка требует супервизора. Reverb нужно запускать через Supervisor или аналогичный process manager, чтобы он перезапускался при падении.

Заключение

Laravel Reverb в 2026 году — это зрелое, production-ready решение для realtime в PHP-приложениях. Он убирает главный барьер: больше не нужен Node.js, не нужен сторонний сервис, не нужны лишние деньги на Pusher. Вы пишете PHP — Reverb доставляет события клиентам по WebSocket.

Начать можно за 15 минут: установил пакет, добавил переменные в .env, запустил php artisan reverb:start — и realtime в вашем Laravel-проекте работает. Дальше — Redis для масштабирования, Docker и Kubernetes для надёжного деплоя.

Экспериментируйте, стройте чаты, дашборды реального времени, live-уведомления — инструмент готов. Стек остаётся чистым PHP, команда Laravel поддерживает Reverb и развивает его. Самое время попробовать.

Технологии

Теги

Руслан Исмаилов

Senior Web / Backend разработчик. Senior web/backend разработчик с 9-летним опытом. Стек: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, микросервисы, CI/CD. Подробнее обо мне →