Laravel Reverb
イントロダクション
Laravel Reverbは、高速でスケーラブルなリアルタイムWebSocket通信をLaravelアプリケーションに直接もたらし、Laravelの既存のイベントブロードキャストツール群とのシームレスな統合を提供します。
インストール
Reverbはinstall:broadcasting Artisanコマンドを使用してインストールできます。
1php artisan install:broadcasting
設定
内部的には、install:broadcasting Artisanコマンドはreverb:installコマンドを実行し、Reverbを妥当なデフォルト設定オプションでインストールします。設定を変更したい場合は、Reverbの環境変数を更新するか、config/reverb.php設定ファイルを更新することで行えます。
アプリケーション認証情報
Reverbへの接続を確立するには、クライアントとサーバ間でReverb「アプリケーション」の認証情報を交換する必要があります。これらの認証情報はサーバ側で設定され、クライアントからのリクエストを検証するために使用されます。これらの認証情報は、以下の環境変数を使用して定義できます。
1REVERB_APP_ID=my-app-id2REVERB_APP_KEY=my-app-key3REVERB_APP_SECRET=my-app-secret
許可するオリジン
config/reverb.php設定ファイルのappsセクションにあるallowed_origins設定の値を更新することで、クライアントリクエストが発信できるオリジンを定義することもできます。許可されたオリジンにリストされていないオリジンからのリクエストはすべて拒否されます。*を使用してすべてのオリジンを許可することもできます。
1'apps' => [2 [3 'app_id' => 'my-app-id',4 'allowed_origins' => ['laravel.com'],5 // ...6 ]7]
追加アプリケーション
通常、ReverbはインストールされたアプリケーションにWebSocketサーバを提供します。しかし、単一のReverbインストールで複数のアプリケーションを提供することも可能です。
例えば、Reverbを介して複数のアプリケーションにWebSocket接続を提供する単一のLaravelアプリケーションを維持したい場合があります。これは、アプリケーションのconfig/reverb.php設定ファイルで複数のappsを定義することで実現できます。
1'apps' => [ 2 [ 3 'app_id' => 'my-app-one', 4 // ... 5 ], 6 [ 7 'app_id' => 'my-app-two', 8 // ... 9 ],10],
SSL
ほとんどの場合、安全なWebSocket接続は、リクエストがReverbサーバにプロキシされる前に、上流のWebサーバ(Nginxなど)によって処理されます。
しかし、ローカル開発中など、Reverbサーバが直接安全な接続を処理すると便利な場合があります。Laravel Herdのセキュアサイト機能を使用している場合、またはLaravel Valetを使用してアプリケーションに対してsecureコマンドを実行した場合、サイト用に生成されたHerd/Valet証明書を使用してReverb接続を保護できます。そのためには、REVERB_HOST環境変数をサイトのホスト名に設定するか、Reverbサーバを起動するときに明示的にhostnameオプションを渡します。
1php 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コンテキストオプションでサポートされているオプションを指定できます。
1'options' => [2 'tls' => [3 'local_cert' => '/path/to/cert.pem'4 ],5],
サーバの実行
Reverbサーバはreverb:start Artisanコマンドで起動できます。
1php artisan reverb:start
デフォルトでは、Reverbサーバは0.0.0.0:8080で起動し、すべてのネットワークインターフェイスからアクセス可能になります。
カスタムホストまたはポートを指定する必要がある場合は、サーバを起動するときに--hostおよび--portオプションを介して指定できます。
1php 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にブロードキャストメッセージを送信する場所を指示します。たとえば、本番環境では、ポート443のパブリックReverbホスト名からのリクエストを、0.0.0.0:8080で動作するReverbサーバにルーティングする場合があります。このシナリオでは、環境変数は次のように定義されます。
1REVERB_SERVER_HOST=0.0.0.02REVERB_SERVER_PORT=80803 4REVERB_HOST=ws.laravel.com5REVERB_PORT=443
デバッグ
パフォーマンスを向上させるため、Reverbはデフォルトではデバッグ情報を出力しません。Reverbサーバを通過するデータのストリームを確認したい場合は、reverb:startコマンドに--debugオプションを指定します。
1php artisan reverb:start --debug
再起動
Reverbは長時間実行されるプロセスであるため、コードの変更はreverb:restart Artisanコマンドでサーバを再起動しないと反映されません。
reverb:restartコマンドは、サーバを停止する前にすべての接続が正常に終了することを保証します。Supervisorなどのプロセス管理ツールでReverbを実行している場合、すべての接続が終了した後にプロセス管理ツールによってサーバが自動的に再起動されます。
1php artisan reverb:restart
モニタリング
ReverbはLaravel Pulseとの統合を介して監視できます。ReverbのPulse統合を有効にすることで、サーバで処理されている接続数とメッセージ数を追跡できます。
統合を有効にするには、まずPulseをインストールしていることを確認してください。次に、Reverbのレコーダーのいずれかをアプリケーションのconfig/pulse.php設定ファイルに追加します。
1use Laravel\Reverb\Pulse\Recorders\ReverbConnections; 2use Laravel\Reverb\Pulse\Recorders\ReverbMessages; 3 4'recorders' => [ 5 ReverbConnections::class => [ 6 'sample_rate' => 1, 7 ], 8 9 ReverbMessages::class => [10 'sample_rate' => 1,11 ],12 13 // ...14],
次に、各レコーダーのPulseカードをPulseダッシュボードに追加します。
1<x-pulse>2 <livewire:reverb.connections cols="full" />3 <livewire:reverb.messages cols="full" />4 ...5</x-pulse>
接続アクティビティは、定期的に新しい更新をポーリングすることで記録されます。この情報がPulseダッシュボードに正しく表示されるようにするには、Reverbサーバでpulse:checkデーモンを実行する必要があります。Reverbを水平スケール構成で実行している場合は、このデーモンをサーバの1つでのみ実行してください。
本番環境でのReverbの実行
WebSocketサーバは長時間実行されるため、Reverbサーバがサーバで利用可能なリソースに対して最適な接続数を効果的に処理できるように、サーバとホスティング環境にいくつかの最適化を行う必要がある場合があります。
サイトがLaravel Forgeによって管理されている場合、「アプリケーション」パネルから直接Reverb用にサーバを自動的に最適化できます。Reverb統合を有効にすると、Forgeは必要な拡張機能のインストールや許可される接続数の増加など、サーバが本番環境に対応できるようにします。
オープンファイル
各WebSocket接続は、クライアントまたはサーバが切断するまでメモリに保持されます。UnixおよびUnixライクな環境では、各接続はファイルで表されます。しかし、オペレーティングシステムレベルとアプリケーションレベルの両方で、許可されるオープンファイルの数にはしばしば制限があります。
オペレーティングシステム
Unixベースのオペレーティングシステムでは、ulimitコマンドを使用して許可されるオープンファイルの数を確認できます。
1ulimit -n
このコマンドは、さまざまなユーザーに許可されているオープンファイルの制限を表示します。これらの値は/etc/security/limits.confファイルを編集することで更新できます。たとえば、forgeユーザーの最大オープンファイル数を10,000に更新するには、次のようになります。
1# /etc/security/limits.conf2forge soft nofile 100003forge hard nofile 10000
イベントループ
内部的に、ReverbはReactPHPイベントループを使用してサーバ上のWebSocket接続を管理します。デフォルトでは、このイベントループはstream_selectによって駆動され、追加の拡張機能は必要ありません。ただし、stream_selectは通常1,024のオープンファイルに制限されています。そのため、1,000以上の同時接続を処理する予定がある場合は、同じ制限に縛られない別のイベントループを使用する必要があります。
Reverbは、利用可能な場合にext-uvで駆動されるループに自動的に切り替わります。このPHP拡張機能は、PECLを介してインストールできます。
1pecl install uv
Webサーバ
ほとんどの場合、ReverbはサーバのWebに面していないポートで実行されます。そのため、Reverbにトラフィックをルーティングするには、リバースプロキシを設定する必要があります。Reverbがホスト0.0.0.0とポート8080で実行されており、サーバがNginx Webサーバを利用していると仮定すると、次のNginxサイト設定を使用してReverbサーバのリバースプロキシを定義できます。
1server { 2 ... 3 4 location / { 5 proxy_http_version 1.1; 6 proxy_set_header Host $http_host; 7 proxy_set_header Scheme $scheme; 8 proxy_set_header SERVER_PORT $server_port; 9 proxy_set_header REMOTE_ADDR $remote_addr;10 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;11 proxy_set_header Upgrade $http_upgrade;12 proxy_set_header Connection "Upgrade";13 14 proxy_pass http://0.0.0.0:8080;15 }16 17 ...18}
Reverbは/appでWebSocket接続をリッスンし、/appsでAPIリクエストを処理します。Reverbリクエストを処理するWebサーバがこれらの両方のURIを提供できることを確認してください。Laravel Forgeを使用してサーバを管理している場合、Reverbサーバはデフォルトで正しく設定されます。
通常、Webサーバはサーバの過負荷を防ぐために許可される接続数を制限するように設定されています。Nginx Webサーバで許可される接続数を10,000に増やすには、nginx.confファイルのworker_rlimit_nofileとworker_connectionsの値を更新する必要があります。
1user forge; 2worker_processes auto; 3pid /run/nginx.pid; 4include /etc/nginx/modules-enabled/*.conf; 5worker_rlimit_nofile 10000; 6 7events { 8 worker_connections 10000; 9 multi_accept on;10}
上記の設定により、プロセスごとに最大10,000のNginxワーカーを生成できます。さらに、この設定はNginxのオープンファイル制限を10,000に設定します。
ポート
Unixベースのオペレーティングシステムでは、通常、サーバで開くことができるポートの数が制限されています。次のコマンドで現在許可されている範囲を確認できます。
1cat /proc/sys/net/ipv4/ip_local_port_range2# 32768 60999
上記の出力は、各接続に空きポートが必要なため、サーバが最大28,231(60,999 - 32,768)の接続を処理できることを示しています。許可される接続数を増やすには水平スケーリングを推奨しますが、サーバの/etc/sysctl.conf設定ファイルで許可されるポート範囲を更新することで、利用可能なオープンポートの数を増やすことができます。
プロセス管理
ほとんどの場合、Supervisorなどのプロセス管理ツールを使用して、Reverbサーバが継続的に実行されるようにする必要があります。Supervisorを使用してReverbを実行している場合は、サーバのsupervisor.confファイルのminfds設定を更新して、SupervisorがReverbサーバへの接続を処理するために必要なファイルを開くことができるようにする必要があります。
1[supervisord]2...3minfds=10000
スケーリング
単一のサーバで許可されるよりも多くの接続を処理する必要がある場合は、Reverbサーバを水平にスケーリングできます。Redisの発行/購読機能を利用して、Reverbは複数のサーバにわたる接続を管理できます。メッセージがアプリケーションのReverbサーバの1つで受信されると、そのサーバはRedisを使用して受信メッセージを他のすべてのサーバに発行します。
水平スケーリングを有効にするには、アプリケーションの.env設定ファイルでREVERB_SCALING_ENABLED環境変数をtrueに設定する必要があります。
1REVERB_SCALING_ENABLED=true
次に、すべてのReverbサーバが通信する専用の中央Redisサーバが必要です。Reverbは、アプリケーションに設定されたデフォルトのRedis接続を使用して、すべてのReverbサーバにメッセージを発行します。
Reverbのスケーリングオプションを有効にし、Redisサーバを設定したら、Redisサーバと通信できる複数のサーバでreverb:startコマンドを呼び出すだけです。これらのReverbサーバは、受信リクエストをサーバ間で均等に分散するロードバランサの背後に配置する必要があります。