Laravel Reverb
简介
Laravel Reverb 为 Laravel 应用带来高速、可扩展的实时 WebSocket 通信,并与现有的事件广播工具无缝集成。
安装
可使用 install:broadcasting Artisan 命令安装 Reverb:
php artisan install:broadcasting配置
幕后,install:broadcasting 会运行 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 服务器。不过,单次安装也可为多个应用提供服务。
例如,你可能希望用一个 Laravel 应用,通过 Reverb 为多个应用提供 WebSocket。可在 config/reverb.php 中定义多个 apps:
'apps' => [
[
'app_id' => 'my-app-one',
// ...
],
[
'app_id' => 'my-app-two',
// ...
],
],SSL
多数情况下,安全 WebSocket 连接由上游 Web 服务器(Nginx 等)处理后再代理到 Reverb 服务器。
但在本地开发等场景下,让 Reverb 直接处理安全连接也会很有用。若使用 Laravel Herd 的安全站点,或使用 Laravel Valet 并对应用执行了 secure 命令,可用为站点生成的证书保护 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默认启动在 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 向何处发送广播消息。例如在生产环境中,可将公网主机名的 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:start 传入 --debug:
php artisan reverb:start --debug重启
由于 Reverb 是长时运行进程,代码变更需通过 reverb:restart 重启服务器后才会生效。
reverb:restart 会在停止服务器前优雅终止所有连接。若用 Supervisor 等进程管理器运行 Reverb,连接全部结束后会由进程管理器自动重启:
php artisan reverb:restart监控
Reverb 可通过与 Laravel Pulse 的集成进行监控。启用后可跟踪服务器处理的连接数与消息数。
启用前请先安装 Pulse,然后将 Reverb 的 recorder 加入 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,
],
// ...
],接着把各 recorder 的 Pulse 卡片加到 Pulse 仪表盘:
<x-pulse>
<livewire:reverb.connections cols="full" />
<livewire:reverb.messages cols="full" />
...
</x-pulse>连接活动通过定期轮询记录。要在 Pulse 仪表盘正确展示,须在 Reverb 服务器上运行 pulse:check 守护进程。若采用水平扩展,只需在其中一台服务器上运行该守护进程。
在生产环境运行 Reverb
由于 WebSocket 服务器长时运行,可能需要对服务器与托管环境做一些优化,以便在现有资源下有效处理尽可能多的连接。
INFO
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 驱动,无需额外扩展,但通常限制为 1,024 个打开文件。若计划处理超过 1,000 个并发连接,需使用不受相同限制的替代事件循环。
若可用,Reverb 会自动切换到 ext-uv 驱动的循环。该 PHP 扩展可通过 PECL 安装:
pecl install uvWeb 服务器
多数情况下,Reverb 运行在非对外暴露的端口上,因此需配置反向代理。假设 Reverb 在 0.0.0.0:8080,且使用 Nginx,可用如下站点配置:
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 在 /app 监听 WebSocket 连接,在 /apps 处理 API 请求。请确保处理 Reverb 请求的 Web 服务器能服务这两个 URI。若使用 Laravel Forge 管理服务器,Reverb 默认会正确配置。
Web 服务器通常会限制连接数以防过载。若要将 Nginx 允许连接数提高到 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,请更新服务器 supervisor.conf 中的 minfds,以便能打开处理连接所需的文件:
[supervisord]
...
minfds=10000扩展
若单台服务器无法承载所需连接数,可水平扩展 Reverb。借助 Redis 的发布/订阅能力,Reverb 可跨多台服务器管理连接。某台 Reverb 收到消息后,会通过 Redis 发布给其他所有服务器。
启用水平扩展时,在 .env 中将 REVERB_SCALING_ENABLED 设为 true:
REVERB_SCALING_ENABLED=true接着需要一台所有 Reverb 服务器都能访问的中央 Redis。Reverb 会使用应用默认 Redis 连接向所有 Reverb 服务器发布消息。
启用扩展并配置 Redis 后,在能与 Redis 通信的多台服务器上运行 reverb:start 即可。这些服务器应放在负载均衡器后,以均匀分发请求。
事件
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。