Laravel Reverb
簡介
Laravel Reverb 為你的 Laravel 應用帶來極速且可擴充套件的即時 WebSocket 通訊,並與 Laravel 現有的事件廣播工具套件實現無縫整合。
安裝
你可以使用 install:broadcasting Artisan 命令安裝 Reverb
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
允許的來源 (Allowed Origins)
你還可以透過更新 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 安裝服務於多個應用。
例如,你可能希望維護一個單一的 Laravel 應用,並透過 Reverb 為多個應用提供 WebSocket 連線。這可以透過在應用的 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 連線由上游 Web 伺服器(如 Nginx 等)處理,然後再將請求代理到你的 Reverb 伺服器。
然而,在某些場景下(例如本地開發期間),讓 Reverb 伺服器直接處理安全連線會很有用。如果你正在使用 Laravel Herd 的安全站點功能,或者你正在使用 Laravel Valet 並針對你的應用運行了 secure 命令,你可以使用為你的站點生成的 Herd / Valet 證書來保護你的 Reverb 連線。要實現這一點,請將 REVERB_HOST 環境變數設定為你的站點主機名,或者在啟動 Reverb 伺服器時顯式傳遞主機名選項。
1php 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 上下文選項。
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 傳送廣播訊息的位置。例如,在生產環境中,你可以將公共 Reverb 主機名埠 443 的請求路由到執行在 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,則只需在其中一臺伺服器上執行該守護程序。
在生產環境中執行 Reverb
由於 WebSocket 伺服器的長駐特性,你可能需要對伺服器和託管環境進行一些最佳化,以確保 Reverb 伺服器能夠根據伺服器可用的資源有效地處理最佳數量的連線。
Laravel Cloud 提供由 Laravel Reverb 叢集驅動的全託管 WebSocket 基礎設施,讓你無需管理基礎設施即可擴充套件並交付啟用了 Reverb 的應用。
開啟的檔案
每個 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 伺服器收到訊息時,它將使用 Redis 將傳入的訊息釋出給所有其他伺服器。
要啟用橫向擴充套件,應在應用的 .env 配置檔案中將 REVERB_SCALING_ENABLED 環境變數設定為 true。
1REVERB_SCALING_ENABLED=true
接下來,你需要一個專用的中央 Redis 伺服器,所有 Reverb 伺服器都將與之通訊。Reverb 將使用為你的應用配置的預設 Redis 連線來向所有 Reverb 伺服器釋出訊息。
一旦啟用了 Reverb 的擴充套件選項並配置了 Redis 伺服器,你只需在多臺能夠與 Redis 伺服器通訊的伺服器上呼叫 reverb:start 命令。這些 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。