Skip to content

Laravel Reverb

はじめに

Laravel Reverb は、Laravelアプリケーションに直接、高速でスケーラブルなリアルタイムWebSocket通信をもたらし、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を使用していて、アプリケーションに対してsecureコマンドを実行している場合、サイト用に生成されたHerd / Valet証明書を使用してReverb接続を保護できます。そのためには、REVERB_HOST環境変数をサイトのホスト名に設定するか、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でアクセス可能になります。

また、アプリケーションの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などのプロセスマネージャでReverbを実行している場合、すべての接続が終了した後、プロセスマネージャによってサーバーが自動的に再起動されます:

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>

本番環境でのReverbの実行

WebSocketサーバーの長時間実行の性質上、Reverbサーバーがサーバー上で利用可能なリソースに対して最適な接続数を効果的に処理できるように、サーバーとホスティング環境にいくつかの最適化を行う必要があるかもしれません。

Note

サイトがLaravel Forgeによって管理されている場合、「Application」パネルから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;
    }

    ...
}

Warning

ReverbはWebSocket接続を /app で、APIリクエストを /apps で待ち受けます。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ベースのオペレーティングシステムは通常、サーバー上で開くことができるポートの数を制限しています。以下のコマンドで現在許可されている範囲を確認できます:

```sh 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>
### プロセス管理

ほとんどの場合、Reverbサーバーが常に実行されていることを確認するために、Supervisorなどのプロセスマネージャを使用する必要があります。Supervisorを使用してReverbを実行している場合、サーバーの`supervisor.conf`ファイルの`minfds`設定を更新して、SupervisorがReverbサーバーへの接続を処理するために必要なファイルを開くことができるようにする必要があります:

```ini
[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サーバーは、受信リクエストをサーバー間で均等に分散するロードバランサーの背後に配置する必要があります。

ユーザーノート