Джерело: https://laravelukraine.com/docs/13.x/reverb

# Laravel Reverb

- [Вступ](#introduction)
- [Встановлення](#installation)
- [Конфігурація](#configuration)
    - [Облікові дані застосунку](#application-credentials)
    - [Дозволені джерела](#allowed-origins)
    - [Додаткові застосунки](#additional-applications)
    - [SSL](#ssl)
- [Запуск сервера](#running-server)
    - [Налагодження](#debugging)
    - [Перезапуск](#restarting)
- [Моніторинг](#monitoring)
- [Reverb у продакшені](#production)
    - [Відкриті файли](#open-files)
    - [Цикл подій](#event-loop)
    - [Вебсервер](#web-server)
    - [Порти](#ports)
    - [Керування процесами](#process-management)
    - [Масштабування](#scaling)
- [Події](#events)

<a name="introduction"></a>
## Вступ

[Laravel Reverb](https://github.com/laravel/reverb) приносить блискавично швидку та масштабовану real-time комунікацію через WebSocket безпосередньо до вашого Laravel-застосунку і безшовно інтегрується з наявним набором [інструментів бродкастингу подій](/docs/{{version}}/broadcasting) Laravel.

<a name="installation"></a>
## Встановлення

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

```shell
php artisan install:broadcasting
```

<a name="configuration"></a>
## Конфігурація

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

<a name="application-credentials"></a>
### Облікові дані застосунку

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

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

<a name="allowed-origins"></a>
### Дозволені джерела

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

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

<a name="additional-applications"></a>
### Додаткові застосунки

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

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

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

<a name="ssl"></a>
### SSL

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

Однак іноді буває корисно, наприклад під час локальної розробки, щоб сервер Reverb обробляв захищені з'єднання напряму. Якщо ви користуєтеся можливістю захищених сайтів [Laravel Herd](https://herd.laravel.com) або використовуєте [Laravel Valet](/docs/{{version}}/valet) і виконали [команду secure](/docs/{{version}}/valet#securing-sites) для свого застосунку, ви можете скористатися згенерованим Herd / Valet сертифікатом для вашого сайту, щоб захистити з'єднання Reverb. Для цього встановіть змінну оточення `REVERB_HOST` на ім'я хоста вашого сайту або явно передайте опцію hostname під час запуску сервера Reverb:

```shell
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](https://www.php.net/manual/en/context.ssl.php):

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

<a name="running-server"></a>
## Запуск сервера

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

```shell
php artisan reverb:start
```

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

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

```shell
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`. У такому сценарії ваші змінні оточення були б визначені так:

```ini
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080

REVERB_HOST=ws.laravel.com
REVERB_PORT=443
```

<a name="debugging"></a>
### Налагодження

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

```shell
php artisan reverb:start --debug
```

<a name="restarting"></a>
### Перезапуск

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

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

```shell
php artisan reverb:restart
```

<a name="monitoring"></a>
## Моніторинг

За Reverb можна стежити через інтеграцію з [Laravel Pulse](/docs/{{version}}/pulse). Увімкнувши інтеграцію Reverb з Pulse, ви зможете відстежувати кількість з'єднань і повідомлень, які обробляє ваш сервер.

Щоб увімкнути інтеграцію, спершу переконайтеся, що ви [встановили Pulse](/docs/{{version}}/pulse#installation). Далі додайте будь-які з рекордерів Reverb до конфігураційного файлу `config/pulse.php` вашого застосунку:

```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](/docs/{{version}}/pulse#dashboard-customization):

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

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

<a name="production"></a>
## Reverb у продакшені

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

> [!NOTE]
> [Laravel Cloud](https://cloud.laravel.com) пропонує повністю керовану WebSocket-інфраструктуру на базі кластерів Laravel Reverb, що дозволяє масштабувати й випускати застосунки з Reverb, не керуючи інфраструктурою.

<a name="open-files"></a>
### Відкриті файли

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

<a name="operating-system"></a>
#### Операційна система

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

```shell
ulimit -n
```

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

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

<a name="event-loop"></a>
### Цикл подій

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

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

```shell
pecl install uv
```

<a name="web-server"></a>
### Вебсервер

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

```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;
    }

    ...
}
```

> [!WARNING]
> Reverb слухає WebSocket-з'єднання на `/app` і обробляє API-запити на `/apps`. Переконайтеся, що вебсервер, який обробляє запити до Reverb, може обслуговувати обидва ці URI. Якщо ви користуєтеся [Laravel Forge](https://forge.laravel.com) для керування серверами, ваш сервер Reverb буде правильно налаштований за замовчуванням.

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

```nginx
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.

<a name="ports"></a>
### Порти

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

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

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

<a name="process-management"></a>
### Керування процесами

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

```ini
[supervisord]
...
minfds=10000
```

<a name="scaling"></a>
### Масштабування

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

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

```env
REVERB_SCALING_ENABLED=true
```

Далі вам потрібен виділений, центральний сервер Redis, з яким взаємодіятимуть усі сервери Reverb. Reverb використовуватиме [підключення Redis, налаштоване для вашого застосунку за замовчуванням](/docs/{{version}}/redis#configuration), щоб публікувати повідомлення для всіх ваших серверів Reverb.

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

<a name="events"></a>
## Події

Reverb диспетчеризує внутрішні події протягом життєвого циклу з'єднання та обробки повідомлень. Ви можете [слухати ці події](/docs/{{version}}/events), щоб виконувати дії, коли керується з'єднаннями чи обмінюється повідомленнями.

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`.