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 服务

相关推荐
工业甲酰苯胺2 小时前
JVM实战—OOM的定位和解决
服务器·jvm·php
芳草萋萋鹦鹉洲哦4 小时前
WebSocket、SSE(Server-Sent Events)、HTTP 和 Axios关系总结
websocket·网络协议·http
码上飞扬17 小时前
探索Python的异步编程:高效处理并发任务
开发语言·python·php·异步编程
007php00717 小时前
如何恢复依赖的go自定义SDK的GoZero项目
java·数据库·python·microsoft·oracle·golang·php
Onlooker-轩逸19 小时前
WebSocket
网络·websocket·网络协议
HelloZheQ20 小时前
从零开始:构建一个简单的聊天应用使用 WebSocket 和 React Native
websocket·网络协议·react native
黑客K-ing20 小时前
什么是网络安全攻防演练,即红蓝对抗?
安全·web安全·php
Kika写代码1 天前
【计算机网络】课程 实验四 配置快速生成树协议(RSTP)
开发语言·计算机网络·php
多客软件佳佳1 天前
基于Thinkphp6+uniapp的陪玩陪聊软件开发方案分析
小程序·uni-app·php·生活·交友