简介
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' => [
[
'app_id' => 'my-app-id',
'allowed_origins' => ['laravel.com'],
// ...
]
]额外应用
通常情况下,Reverb 为其安装所在的应用提供一个 WebSocket 服务器。然而,也有可能使用单个 Reverb 安装为多个应用提供服务。
例如,您可能希望维护一个单一的 Laravel 应用,通过 Reverb 为多个应用提供 WebSocket 连接。这可以通过在应用的 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 服务器时显式传递 hostname 选项:
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:start Artisan 命令来启动 Reverb 服务器:
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监控
可以通过与 Laravel Pulse 的集成来监控 Reverb。启用 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>连接活动是通过定期轮询新更新来记录的。为确保该信息在 Pulse 仪表板上正确呈现,您必须在 Reverb 服务器上运行 pulse:check 守护进程。如果您以水平扩展配置运行 Reverb,则只需在其中一个服务器上运行此守护进程。
在生产环境中运行 Reverb
由于 WebSocket 服务器具有长期运行的特性,您可能需要对服务器和托管环境进行一些优化,以确保 Reverb 服务器能够有效地为服务器可用资源处理最优数量的连接。
Laravel Cloud 提供由 Laravel Reverb 集群支持的全托管 WebSocket 基础设施,让您无需管理基础设施即可扩展和交付启用了 Reverb 的应用。
打开的文件
每个 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 通常会受到最多 1024 个打开文件的限制。因此,如果你计划处理超过 1000 个并发连接,就需要使用不受此类限制的替代事件循环。
当环境可用时,Reverb 会自动切换到由 ext-uv 驱动的循环。可以通过 PECL 安装该 PHP 扩展:
pecl install uvWeb 服务器
在大多数情况下,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;
}
...
} Reverb 会在 /app 监听 WebSocket 连接,并在 /apps 处理 API 请求。你应该确保处理 Reverb 请求的 Web 服务器能够同时服务这两个 URI。如果你使用 Laravel Forge 来管理服务器,你的 Reverb 服务器将默认被正确配置。
通常,为了防止服务器过载,Web 服务器会配置允许的连接数量上限。若要将 Nginx Web 服务器的允许连接数提升至 10,000,需要更新 nginx.conf 文件中的 worker_rlimit_nofile 和 worker_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 worker。此外,此配置还将 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 服务器接收到消息时,该服务器会通过 Redis 将传入消息发布给所有其他服务器。
要启用水平扩展,你需要在应用的 .env 配置文件中将 REVERB_SCALING_ENABLED 环境变量设置为 true:
REVERB_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。