Laravel 新 WebSocket 服务 Reverb 使用指南

旧篇 => Laravel/Lumen 中使用 Echo + Socket.IO-Client 实现网页即时通讯广播 https://blog.csdn.net/maxsky/article/details/130394420 已过时

与时俱进,Laravel 官方在 2024 年 7 月发布了 laravel/reverb 包的正式版,因为之前使用的 laravel-echo-server 所使用的 socket.io-client 是比较老旧的 2.0 版本(而且是依赖 NodeJS,内存占用高)

所以更新了此博文帮助大家入门 laravel/reverb 的使用

内容与之前博文大同小异,我亦同步更新了 Laravel Echo 客户端的 Demo 供大家参考

laravel/reverb 最低支持框架版本为 Laravel 10.47+ 以及 PHP 8.2,博文发布时 Laravel 10 版本为 10.48.25,此处使用该框架作为示例(官方宣称当前没有计划支持 Lumen 框架

安装

执行 composer require laravel/reverb 安装 Reverb 即可

如果遇到网络问题,可参考该博文解决:Composer 2 镜像处理方案

安装成功后在项目根目录运行 php artisan,可以看到 reverb 相关命令表示安装成功

配置

因为在 Laravel 10 中不存在 php artisan install 命令,所以部分工作需要我们手动完成

首先执行

bash 复制代码
php artisan reverb:install

该命令行会在 Laravel 10 框架中卡住,我们只需要检查下方相关内容是否成功变更后中断执行即可

  1. 检查 config/app.php 文件底部 providers 部分 是否取消注释 // App\Providers\BroadcastServiceProvider::class, 行,如果没有请手动取消,使 BroadcastServiceProvider 类启用;

  2. 检查 config/broadcasting.php 文件 connections 部分是否出现了 reverb 连接内容;

  3. 检查 config 目录中是否出现了 reverb.php 配置文件;

  4. 检查根目录 .env 文件是否新增了 类似 如下内容:

    c 复制代码
    REVERB_APP_ID=122822
    REVERB_APP_KEY=1vskpuauarymbej0on7d
    REVERB_APP_SECRET=nyk2kyajfnb0h86yrnoh
    REVERB_HOST="localhost"
    REVERB_PORT=8080
    REVERB_SCHEME=http
    
    VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
    VITE_REVERB_HOST="${REVERB_HOST}"
    VITE_REVERB_PORT="${REVERB_PORT}"
    VITE_REVERB_SCHEME="${REVERB_SCHEME}"

    需特别注意在命令执行期间可能造成 .env 中出现连续两个空行的情况,请自行删掉一行

如果上方 项没有问题,可以 中断 reverb:install 命令

因为 Reverb 同样依赖了广播服务,我们需要在 .env 中修改或新增:

c 复制代码
BROADCAST_DRIVER=reverb

发送广播

广播由事件组成,也就是说 因为发生了什么事,需要通知给某个人或者直接公布(所有人)

或者这样形容:广播就是喇叭,事件是通过喇叭"吼叫"(通知/发送)出去的。这就是我们需要创建事件的原因

事件

执行下方命令创建事件类 TestEvent

bash 复制代码
php artisan make:event TestEvent

该命令会在 app/Events 目录下创建 TestEvent 类。目前这个类非常简单,他有一个 broadcastOn 方法,也就是 通知给谁

注意这里默认的通知是一个 PrivateChannel,也就是 私有频道 。为了更简单的完成我们的示例,我们将其更改为 Channel,并将中间的字符串更改为 channel-pub(意为公共频道 public)

接着我们再为该类新增 public 修饰符的 $message$broadcastTime 成员变量并修改构造函数,现在代码看起来是这样:

php 复制代码
public string $message;
public string $broadcastTime;

/**
 * Create a new event instance.
 */
public function __construct(string $message) {
    $this->message = $message;
    $this->broadcastTime = Carbon::now()->toDateTimeString();
}

广播

上方我们虽然创建了需要广播的事件,但是这个事件并不会被(通过)广播发出去,因为事件类需要 实现 Illuminate\Contracts\Broadcasting\ShouldBroadcastIlluminate\Contracts\Broadcasting\ShouldBroadcastNow 接口

ShouldBroadcastNow立即广播 ,而 ShouldBroadcast异步广播 。根据需求你也应该知道使用哪一个接口,这里我们首先使用 ShouldBroadcastNow 进行接下来的操作

当前整个类的代码如下:

php 复制代码
<?php

namespace App\Events;

use Carbon\Carbon;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class TestEvent implements ShouldBroadcastNow {

    use Dispatchable, InteractsWithSockets, SerializesModels;

    public string $message;
    public string $broadcastTime;

    /**
     * Create a new event instance.
     */
    public function __construct(string $message) {
        $this->message = $message;
        $this->broadcastTime = Carbon::now()->toDateTimeString();
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, Channel>
     */
    public function broadcastOn(): array {
        return [
            new Channel('channel-pub'),
        ];
    }
}

测试发送广播

和旧篇一样,编写一个测试路由即可。为了方便,我们在 routes/web.php 上方新增一个 Get 路由:

php 复制代码
Route::get('/test_broadcast', function () {
    event((new App\Events\TestEvent('测试消息,Hello')));

    return 'Event broadcasted!';
});

然后继续下面的操作

接收广播

运行 Reverb 服务,在项目根目录执行:php artisan reverb:start --debug,加上 debug 参数便于我们查询运行情况

如果没有问题,你会得到如下提示:

复制代码
 INFO  Starting server on 0.0.0.0:8080 (localhost).

注意这个 0.0.0.08080 是基于 config/reverb.php 配置文件中的 hostport 决定

你可以在 .env 中配置 REVERB_SERVER_HOSTREVERB_SERVER_PORT 进行更改。该配置主要决定 Reverb 服务的地址和端口

下方提供两种方式进行测试,大家可以选择自己方便的一种即可

WebSocket 测试软件

例如 Postman、Apifox 等,这里以 Apifox 为例

在 Apifox 中新建 WebSocket 接口,接口地址填入 ws://127.0.0.1:8080/app/REVERB_APP_KEY。注意把 REVERB_APP_KEY 替换为你 .env 文件中对应值,8080 端口对应 REVERB_SERVER_HOST

这里 127.0.0.1 似乎不能用 localhost 代替

填入地址后点击 连接,如果没有问题将得到下方结果:

json 复制代码
{
    "event": "pusher:connection_established",
    "data": "{\"socket_id\":\"676776035.185533755\",\"activity_timeout\":30}"
}

接着在消息中填入下方内容并点击 发送

json 复制代码
{
    "event": "pusher:subscribe",
    "data": {
        "auth": "",
        "channel": "channel-pub"
    }
}

得到订阅成功通知:

json 复制代码
{
    "event": "pusher_internal:subscription_succeeded",
    "data": "{}",
    "channel": "channel-pub"
}

此时可以打开浏览器请求你项目的路由 /test_broadcast,浏览器会显示 Event broadcasted! 表明广播已发送。

注意如果连接断开,重新连接并重新发送消息订阅即可

如果没有问题,你会收到类似下方广播内容表明接收成功:

json 复制代码
{
    "event": "App\\Events\\TestEvent",
    "data":"{\"message\":\"\中\文\测\试\",\"broadcastTime\":\"2025-01-08 03:05:20\"}",
    "channel": "channel-pub"
}

Laravel-Echo-Client-Demo

这是一个前端 Demo 便于调试,地址:https://github.com/maxsky/Laravel-Echo-Client-Demo

通过 git 命令 clone 到本地后按 README.md 操作即可

在浏览器中运行该项目,然后请求 /test_broadcast 路由将会得到类似下方结果:

你也可以多次请求,网页内容不会清空:


以上就是即时广播的收发

异步广播

前文有提到,ShouldBroadcastNow立即广播 ,而 ShouldBroadcast异步广播 。异步广播依赖 Redis 队列,所以在 .env 中需要配置好 Redis 连接以及修改 QUEUE_CONNECTION 配置为 redis

队列名

队列名在事件类中指定,我们在 TestEvent 类中添加下方内容:

php 复制代码
public string $queue = 'broadcast';

在未指定的情况下,事件会存入 default 默认队列

此时新开命令窗口,在项目根目录下执行:

bash 复制代码
php artisan queue:work --queue=broadcast

随后浏览器中刷新请求 /test_broadcast 测试路由。有没有发现一个有趣的事,接收到的消息变成了:

json 复制代码
{
  "queue": "broadcast",
  "message": "测试消息,Hello",
  "broadcastTime": "2025-01-08 03:21:28"
}

没错,默认情况下 消息会将所有 public 成员变量广播出去,让我们接着修改

指定广播内容

TestEvent 类中新增 broadcastWith 方法指定广播内容,经过一系列的修改,现在事件类看起来是这样:

php 复制代码
<?php

namespace App\Events;

use Carbon\Carbon;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class TestEvent implements ShouldBroadcast {

    use Dispatchable, InteractsWithSockets, SerializesModels;

    public string $queue = 'broadcast';

    public string $message;
    public string $broadcastTime;

    /**
     * Create a new event instance.
     */
    public function __construct(string $message) {
        $this->message = $message;
        $this->broadcastTime = Carbon::now()->toDateTimeString();
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, Channel>
     */
    public function broadcastOn(): array {
        return [
            new Channel('channel-pub'),
        ];
    }

    /**
     * @return array
     */
    public function broadcastWith(): array {
        return [
            'name' => 'MyTestEvent',
            'message' => $this->message,
            'broadcastTime' => $this->broadcastTime
        ];
    }
}

可以注意到我们在 broadcastWith 中手动指定了返回内容,我们 重新启动队列 (修改事件后队列需要重启才会生效)并再次请求 /test_broadcast 路由:

我们成功过滤了 queue 成员变量,这保障了我们的隐私信息不会暴露出去

最后

Laravel Reverb 简化了操作和授权,具体的授权可参阅官方文档

熟悉之前 Socket.IO-Client 方式的小伙伴能更快上手,美中不足的是官方没有支持 Lumen 框架的计划

此外在 Laravel-Echo-Client-Demojs/app.js 代码内有相关说明,需要修改对应的 REVERB_APP_KEY 之类才可成功连接到 Reverb 服务

相关推荐
CSharp精选营4 天前
WebSocket 快速入门教程(附示例源码)
websocket·教程·csharp·实时通信·asp.net-core
DigitalOcean11 天前
Laravel 开发者已在 DigitalOcean 上开通超过 10 万台服务器
前端·laravel
两个人的幸福13 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo15 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack15 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820716 天前
PHP 扩展——从入门到理解
php
鹏仔先生17 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下17 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip17 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒17 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php