コンテンツにスキップ

Laravel Reverb

はじめに

Laravel Reverb は、超高速でスケーラブルなリアルタイム WebSocket 通信を Laravel アプリケーションに直接もたらし、Laravel の既存のイベントブロードキャストツールスイートとシームレスに統合します。

インストール

`install:broadcasting` Artisan コマンドを使用して Reverb をインストールできます

php artisan install:broadcasting

設定

バックグラウンドでは、 `install:broadcasting` Artisan コマンドは `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

許可されたオリジン

また、 `config/reverb.php` 設定ファイルの `apps` セクション内で `allowed_origins` 設定値の値を更新することにより、クライアントリクエストの送信元となるオリジンを定義することもできます。許可されたオリジンにリストされていないオリジンからのリクエストは拒否されます。 `*` を使用してすべてのオリジンを許可できます

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

追加アプリケーション

通常、Reverb はインストールされているアプリケーションの WebSocket サーバーを提供します。ただし、単一の Reverb インストールを使用して複数のアプリケーションを提供することも可能です。

たとえば、Reverb を介して複数のアプリケーションに WebSocket 接続を提供する単一の Laravel アプリケーションを維持したい場合があります。これは、アプリケーションの `config/reverb.php` 設定ファイルで複数の `apps` を定義することで実現できます

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

SSL

ほとんどの場合、安全な WebSocket 接続は、リクエストが Reverb サーバーにプロキシされる前に、アップストリーム Web サーバー(Nginx など)によって処理されます。

ただし、ローカル開発中など、Reverb サーバーが安全な接続を直接処理する方が便利な場合があります。Laravel Herd のセキュアサイト機能を使用している場合、またはLaravel Valet を使用していてアプリケーションに対してセキュアコマンドを実行した場合、サイト用に生成された Herd / Valet 証明書を使用して Reverb 接続を保護できます。これを行うには、 `REVERB_HOST` 環境変数をサイトのホスト名に設定するか、Reverb サーバーの起動時にホスト名オプションを明示的に渡します

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

Herd および Valet ドメインは `localhost` に解決されるため、上記のコマンドを実行すると、Reverb サーバーは `wss://laravel.test:8080` でセキュア WebSocket プロトコル( `wss` )を介してアクセスできるようになります。

アプリケーションの `config/reverb.php` 設定ファイルで `tls` オプションを定義することにより、手動で証明書を選択することもできます。 `tls` オプションの配列内では、PHP の SSL コンテキストオプションでサポートされている任意のオプションを指定できます

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

サーバーの実行

Reverb サーバーは、 `reverb:start` Artisan コマンドを使用して起動できます

php artisan reverb:start

デフォルトでは、Reverb サーバーは `0.0.0.0:8080` で起動され、すべてのネットワークインターフェースからアクセスできます。

カスタムホストまたはポートを指定する必要がある場合は、サーバーの起動時に `--host` および `--port` オプションを使用して指定できます

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

または、アプリケーションの `.env` 設定ファイルで `REVERB_SERVER_HOST` および `REVERB_SERVER_PORT` 環境変数を定義することもできます。

`REVERB_SERVER_HOST` および `REVERB_SERVER_PORT` 環境変数は、 `REVERB_HOST` および `REVERB_PORT` と混同しないでください。前者は Reverb サーバー自体を実行するホストとポートを指定しますが、後者のペアは Laravel にブロードキャストメッセージを送信する場所を指示します。たとえば、本番環境では、パブリック Reverb ホスト名からのリクエストをポート `443` で `0.0.0.0:8080` で動作する Reverb サーバーにルーティングする場合があります。このシナリオでは、環境変数は次のように定義されます

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` Artisan コマンドで再起動しないと、コードの変更は反映されません。

`reverb:restart` コマンドは、サーバーを停止する前にすべての接続が正常に終了することを保証します。Supervisor などのプロセス manager で Reverb を実行している場合、すべての接続が終了した後、プロセス manager によってサーバーが自動的に再起動されます

php artisan reverb:restart

監視

Reverb は、Laravel Pulse との統合を介して監視できます。Reverb の Pulse 統合を有効にすることで、サーバーで処理されている接続数とメッセージ数を追跡できます。

統合を有効にするには、最初にPulse をインストールしていることを確認する必要があります。次に、アプリケーションの `config/pulse.php` 設定ファイルに Reverb のレコーダーを追加します

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>

本番環境での Reverb の実行

WebSocket サーバーは長時間実行されるため、サーバーとホスティング環境を最適化して、Reverb サーバーがサーバーで使用可能なリソースに対して最適な数の接続を効果的に処理できるようにする必要がある場合があります。

lightbulb

サイトがLaravel Forgeによって管理されている場合は、「アプリケーション」パネルから Reverb 用にサーバーを自動的に最適化できます。Reverb 統合を有効にすることで、Forge は必要な拡張機能のインストールや許可される接続数の増加など、サーバーが本番環境に対応できるようになります。

開いているファイル

各 WebSocket 接続は、クライアントまたはサーバーのいずれかが切断するまでメモリに保持されます。Unix および Unix ライクな環境では、各接続はファイルで表されます。ただし、オペレーティングシステムとアプリケーションレベルの両方で、許可される開いているファイルの数に制限があることがよくあります。

オペレーティングシステム

Unix ベースのオペレーティングシステムでは、 `ulimit` コマンドを使用して許可される開いているファイルの数を決定できます

ulimit -n

このコマンドは、異なるユーザーに許可されている開いているファイルの制限を表示します。これらの値は、 `/etc/security/limits.conf` ファイルを編集することで更新できます。たとえば、 `forge` ユーザーの開いているファイルの最大数を 10,000 に更新するには、次のようにします

# /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

Webサーバー

ほとんどの場合、ReverbはサーバーのWebに公開されていないポートで実行されます。そのため、Reverbへのトラフィックをルーティングするには、リバースプロキシを設定する必要があります。Reverbがホスト0.0.0.0とポート8080で実行されており、サーバーがNginx Webサーバーを使用していると仮定すると、次のNginxサイト設定を使用してReverbサーバーのリバースプロキシを定義できます。

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;
}
 
...
}
exclamation

Reverbは/appでWebSocket接続をリッスンし、/appsでAPIリクエストを処理します。Reverbリクエストを処理するWebサーバーがこれらの両方のURIを提供できることを確認する必要があります。Laravel Forgeを使用してサーバーを管理している場合、Reverbサーバーはデフォルトで正しく設定されます。

通常、Webサーバーはサーバーの過負荷を防ぐために、許可される接続数を制限するように設定されています。Nginx Webサーバーで許可される接続数を10,000に増やすには、nginx.confファイルのworker_rlimit_nofileworker_connectionsの値を更新する必要があります。

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サーバーが継続的に実行されていることを確認する必要があります。Supervisorを使用してReverbを実行している場合は、サーバーのsupervisor.confファイルのminfds設定を更新して、SupervisorがReverbサーバーへの接続を処理するために必要なファイルを開くことができるようにする必要があります。

[supervisord]
...
minfds=10000

スケーリング

単一のサーバーで許可されるよりも多くの接続を処理する必要がある場合は、Reverbサーバーを水平方向にスケーリングできます。Redisのパブリッシュ/サブスクライブ機能を利用することで、Reverbは複数のサーバーにわたる接続を管理できます。アプリケーションのReverbサーバーの1つがメッセージを受信すると、サーバーはRedisを使用して受信メッセージを他のすべてのサーバーにパブリッシュします。

水平スケーリングを有効にするには、アプリケーションの.env設定ファイルでREVERB_SCALING_ENABLED環境変数をtrueに設定する必要があります。

REVERB_SCALING_ENABLED=true

次に、すべてのReverbサーバーが通信する専用の集中型Redisサーバーを用意する必要があります。Reverbは、アプリケーション用に設定されたデフォルトのRedis接続を使用して、すべてのReverbサーバーにメッセージをパブリッシュします。

Reverbのスケーリングオプションを有効にし、Redisサーバーを設定したら、Redisサーバーと通信できる複数のサーバーでreverb:startコマンドを呼び出すだけです。これらのReverbサーバーは、受信リクエストをサーバー間で均等に分散するロードバランサーの背後に配置する必要があります。