Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас

Laravel Reverb

Вступ

Laravel Reverb приносить блискавично швидку та масштабовану real-time комунікацію через WebSocket безпосередньо до вашого Laravel-застосунку і безшовно інтегрується з наявним набором інструментів бродкастингу подій Laravel.

Встановлення

Встановити Reverb можна артизан-командою install:broadcasting:

php artisan install:broadcasting

Конфігурація

Під капотом артизан-команда install:broadcasting запустить команду reverb:install, яка встановить Reverb з розумним набором параметрів конфігурації за замовчуванням. Якщо ви захочете щось змінити в конфігурації, зробіть це через змінні оточення Reverb або через конфігураційний файл config/reverb.php.

Облікові дані застосунку

Щоб установити з'єднання з Reverb, клієнт і сервер мають обмінятися набором облікових даних «застосунку» Reverb. Ці облікові дані налаштовуються на сервері й використовуються для перевірки запиту від клієнта. Визначити їх можна за допомогою таких змінних оточення:

REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret

Дозволені джерела

Ви також можете визначити джерела, з яких можуть надходити клієнтські запити, змінивши значення allowed_origins у секції apps конфігураційного файлу config/reverb.php. Будь-які запити з джерела, якого немає у списку дозволених, будуть відхилені. Дозволити всі джерела можна за допомогою *:

'apps' => [
    [
        'app_id' => 'my-app-id',
        'allowed_origins' => ['laravel.com'],
        // ...
    ]
]

Додаткові застосунки

Зазвичай Reverb надає WebSocket-сервер для того застосунку, у якому його встановлено. Однак одна інсталяція Reverb може обслуговувати більше ніж один застосунок.

Наприклад, ви можете захотіти підтримувати один Laravel-застосунок, який через Reverb забезпечує WebSocket-з'єднання для кількох застосунків. Цього можна досягти, визначивши кілька apps у конфігураційному файлі config/reverb.php вашого застосунку:

'apps' => [
    [
        'app_id' => 'my-app-one',
        // ...
    ],
    [
        'app_id' => 'my-app-two',
        // ...
    ],
],

SSL

У більшості випадків захищені WebSocket-з'єднання обробляє вищестоящий вебсервер (Nginx тощо), перш ніж запит буде пропрокси́йовано до вашого сервера Reverb.

Однак іноді буває корисно, наприклад під час локальної розробки, щоб сервер Reverb обробляв захищені з'єднання напряму. Якщо ви користуєтеся можливістю захищених сайтів Laravel Herd або використовуєте Laravel Valet і виконали команду secure для свого застосунку, ви можете скористатися згенерованим Herd / Valet сертифікатом для вашого сайту, щоб захистити з'єднання Reverb. Для цього встановіть змінну оточення REVERB_HOST на ім'я хоста вашого сайту або явно передайте опцію hostname під час запуску сервера Reverb:

php artisan reverb:start --host="0.0.0.0" --port=8080 --hostname="laravel.test"

Оскільки домени Herd і Valet резолвляться в localhost, після виконання наведеної вище команди ваш сервер Reverb буде доступний через захищений протокол WebSocket (wss) за адресою wss://laravel.test:8080.

Ви також можете вибрати сертифікат вручну, визначивши опції tls у конфігураційному файлі config/reverb.php вашого застосунку. У масиві опцій tls можна вказати будь-яку з опцій, які підтримують SSL-контексти PHP:

'options' => [
    'tls' => [
        'local_cert' => '/path/to/cert.pem'
    ],
],

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

Сервер Reverb запускається артизан-командою reverb:start:

php artisan reverb:start

За замовчуванням сервер Reverb запускається на 0.0.0.0:8080, тобто доступний з усіх мережевих інтерфейсів.

Якщо вам потрібно вказати власний хост чи порт, зробіть це за допомогою опцій --host і --port під час запуску сервера:

php artisan reverb:start --host=127.0.0.1 --port=9000

Або ж ви можете визначити змінні оточення REVERB_SERVER_HOST і REVERB_SERVER_PORT у конфігураційному файлі .env вашого застосунку.

Змінні оточення REVERB_SERVER_HOST і REVERB_SERVER_PORT не слід плутати з REVERB_HOST і REVERB_PORT. Перші вказують хост і порт, на яких запускається сам сервер Reverb, а друга пара повідомляє Laravel, куди надсилати бродкаст-повідомлення. Наприклад, у продакшен-середовищі ви можете спрямовувати запити з публічного імені хоста Reverb на порту 443 до сервера Reverb, що працює на 0.0.0.0:8080. У такому сценарії ваші змінні оточення були б визначені так:

REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080

REVERB_HOST=ws.laravel.com
REVERB_PORT=443

Налагодження

Задля продуктивності Reverb за замовчуванням не виводить жодної налагоджувальної інформації. Якщо ви хочете бачити потік даних, що проходить через ваш сервер Reverb, додайте до команди reverb:start опцію --debug:

php artisan reverb:start --debug

Перезапуск

Оскільки Reverb - це довготривалий процес, зміни у вашому коді не застосуються, доки ви не перезапустите сервер артизан-командою reverb:restart.

Команда reverb:restart гарантує, що всі з'єднання будуть коректно завершені, перш ніж сервер зупиниться. Якщо ви запускаєте Reverb під менеджером процесів на кшталт Supervisor, після завершення всіх з'єднань менеджер процесів автоматично перезапустить сервер:

php artisan reverb:restart

Моніторинг

За Reverb можна стежити через інтеграцію з Laravel Pulse. Увімкнувши інтеграцію Reverb з Pulse, ви зможете відстежувати кількість з'єднань і повідомлень, які обробляє ваш сервер.

Щоб увімкнути інтеграцію, спершу переконайтеся, що ви встановили Pulse. Далі додайте будь-які з рекордерів Reverb до конфігураційного файлу config/pulse.php вашого застосунку:

use Laravel\Reverb\Pulse\Recorders\ReverbConnections;
use Laravel\Reverb\Pulse\Recorders\ReverbMessages;

'recorders' => [
    ReverbConnections::class => [
        'sample_rate' => 1,
    ],

    ReverbMessages::class => [
        'sample_rate' => 1,
    ],

    // ...
],

Далі додайте картки Pulse для кожного рекордера до вашої панелі Pulse:

<x-pulse>
    <livewire:reverb.connections cols="full" />
    <livewire:reverb.messages cols="full" />
    ...
</x-pulse>

Активність з'єднань записується шляхом періодичного опитування нових оновлень. Щоб ця інформація коректно відображалася на панелі Pulse, ви маєте запустити демон pulse:check на вашому сервері Reverb. Якщо ви запускаєте Reverb у горизонтально масштабованій конфігурації, цей демон слід запускати лише на одному з ваших серверів.

Reverb у продакшені

Через довготривалу природу WebSocket-серверів вам, можливо, доведеться дещо оптимізувати ваш сервер і хостинг-середовище, щоб ваш сервер Reverb міг ефективно обробляти оптимальну кількість з'єднань для доступних на сервері ресурсів.

Laravel Cloud пропонує повністю керовану WebSocket-інфраструктуру на базі кластерів Laravel Reverb, що дозволяє масштабувати й випускати застосунки з Reverb, не керуючи інфраструктурою.

Відкриті файли

Кожне WebSocket-з'єднання тримається в пам'яті, доки не від'єднається клієнт або сервер. У Unix і Unix-подібних середовищах кожне з'єднання представлене файлом. Однак часто існують обмеження на кількість дозволених відкритих файлів як на рівні операційної системи, так і на рівні застосунку.

Операційна система

В операційній системі на базі Unix дозволену кількість відкритих файлів можна дізнатися командою ulimit:

ulimit -n

Ця команда покаже обмеження на відкриті файли для різних користувачів. Змінити ці значення можна, відредагувавши файл /etc/security/limits.conf. Наприклад, збільшення максимальної кількості відкритих файлів до 10 000 для користувача forge виглядало б так:

# /etc/security/limits.conf
forge        soft  nofile  10000
forge        hard  nofile  10000

Цикл подій

Під капотом Reverb використовує цикл подій ReactPHP для керування WebSocket-з'єднаннями на сервері. За замовчуванням цей цикл подій працює на stream_select, який не потребує жодних додаткових розширень. Однак stream_select зазвичай обмежений 1 024 відкритими файлами. Тому, якщо ви плануєте обробляти понад 1 000 одночасних з'єднань, вам знадобиться альтернативний цикл подій, не обмежений тими самими рамками.

Reverb автоматично перемкнеться на цикл на базі ext-uv, коли той доступний. Це розширення PHP можна встановити через PECL:

pecl install uv

Вебсервер

У більшості випадків Reverb працює на порту вашого сервера, не зверненому до вебу. Тож, щоб спрямувати трафік до Reverb, вам слід налаштувати зворотний проксі. Припускаючи, що Reverb працює на хості 0.0.0.0 і порту 8080, а ваш сервер використовує вебсервер Nginx, зворотний проксі для вашого сервера Reverb можна визначити такою конфігурацією сайту Nginx:

server {
    ...

    location / {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_pass http://0.0.0.0:8080;
    }

    ...
}

Reverb слухає WebSocket-з'єднання на /app і обробляє API-запити на /apps. Переконайтеся, що вебсервер, який обробляє запити до Reverb, може обслуговувати обидва ці URI. Якщо ви користуєтеся Laravel Forge для керування серверами, ваш сервер Reverb буде правильно налаштований за замовчуванням.

Зазвичай вебсервери налаштовані обмежувати кількість дозволених з'єднань, щоб запобігти перевантаженню сервера. Щоб збільшити кількість дозволених з'єднань на вебсервері Nginx до 10 000, слід оновити значення worker_rlimit_nofile і worker_connections у файлі nginx.conf:

user forge;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
worker_rlimit_nofile 10000;

events {
  worker_connections 10000;
  multi_accept on;
}

Наведена вище конфігурація дозволить породжувати до 10 000 воркерів Nginx на процес. Крім того, вона встановлює обмеження Nginx на відкриті файли в 10 000.

Порти

Операційні системи на базі Unix зазвичай обмежують кількість портів, які можна відкрити на сервері. Побачити поточний дозволений діапазон можна такою командою:

cat /proc/sys/net/ipv4/ip_local_port_range
# 32768	60999

Наведений вище вивід показує, що сервер може обробити максимум 28 231 (60 999 - 32 768) з'єднань, оскільки кожне з'єднання потребує вільного порту. Хоча для збільшення кількості дозволених з'єднань ми рекомендуємо горизонтальне масштабування, ви можете збільшити кількість доступних відкритих портів, змінивши дозволений діапазон портів у конфігураційному файлі /etc/sysctl.conf вашого сервера.

Керування процесами

У більшості випадків вам слід використовувати менеджер процесів на кшталт Supervisor, щоб сервер Reverb працював безперервно. Якщо ви запускаєте Reverb через Supervisor, оновіть налаштування minfds у файлі supervisor.conf вашого сервера, щоб Supervisor міг відкрити файли, потрібні для обробки з'єднань із вашим сервером Reverb:

[supervisord]
...
minfds=10000

Масштабування

Якщо вам потрібно обробляти більше з'єднань, ніж дозволяє один сервер, ви можете масштабувати сервер Reverb горизонтально. Використовуючи можливості publish / subscribe Redis, Reverb може керувати з'єднаннями на кількох серверах. Коли один із серверів Reverb вашого застосунку отримує повідомлення, він через Redis опублікує вхідне повідомлення для всіх інших серверів.

Щоб увімкнути горизонтальне масштабування, встановіть змінну оточення REVERB_SCALING_ENABLED у true в конфігураційному файлі .env вашого застосунку:

REVERB_SCALING_ENABLED=true

Далі вам потрібен виділений, центральний сервер Redis, з яким взаємодіятимуть усі сервери Reverb. Reverb використовуватиме підключення Redis, налаштоване для вашого застосунку за замовчуванням, щоб публікувати повідомлення для всіх ваших серверів Reverb.

Щойно ви увімкнете опцію масштабування Reverb і налаштуєте сервер Redis, вам достатньо виконати команду reverb:start на кількох серверах, здатних взаємодіяти з вашим сервером Redis. Ці сервери Reverb слід розмістити за балансувальником навантаження, який рівномірно розподіляє вхідні запити між серверами.

Події

Reverb диспетчеризує внутрішні події протягом життєвого циклу з'єднання та обробки повідомлень. Ви можете слухати ці події, щоб виконувати дії, коли керується з'єднаннями чи обмінюється повідомленнями.

Reverb диспетчеризує такі події:

Laravel\Reverb\Events\ChannelCreated

Диспетчеризується, коли створюється канал. Зазвичай це відбувається, коли перше з'єднання підписується на конкретний канал. Подія отримує екземпляр Laravel\Reverb\Protocols\Pusher\Channel.

Laravel\Reverb\Events\ChannelRemoved

Диспетчеризується, коли канал видаляється. Зазвичай це відбувається, коли останнє з'єднання відписується від каналу. Подія отримує екземпляр Laravel\Reverb\Protocols\Pusher\Channel.

Laravel\Reverb\Events\ConnectionPruned

Диспетчеризується, коли сервер прибирає застаріле з'єднання. Подія отримує екземпляр Laravel\Reverb\Contracts\Connection.

Laravel\Reverb\Events\MessageReceived

Диспетчеризується, коли отримано повідомлення від клієнтського з'єднання. Подія отримує екземпляр Laravel\Reverb\Contracts\Connection і сирий рядок $message.

Laravel\Reverb\Events\MessageSent

Диспетчеризується, коли повідомлення надіслано до клієнтського з'єднання. Подія отримує екземпляр Laravel\Reverb\Contracts\Connection і сирий рядок $message.