在 Laravel 12 中实现 WebSocket 通信

在 Laravel 12 中实现 WebSocket 通信主要有两种主流方案:‌官方推荐的 Laravel Reverb‌ 和 ‌第三方库(如 Soketi/Pusher 或 Workerman/Swoole)‌。以下是详细实现步骤:

一、官方方案:Laravel Reverb(推荐)

Laravel Reverb 是 Laravel 官方推出的高性能 WebSocket 服务,完全集成到框架中,适合标准实时场景(如聊天、通知)。

1. 安装 Laravel Reverb

bash 复制代码
composer require laravel/reverb
php artisan reverb:install

2. 配置环境变量(.env)

env 复制代码
BROADCAST_DRIVER=reverb   # 设置广播驱动为 Reverb
REVERB_SERVER_HOST=0.0.0.0  # 监听地址
REVERB_SERVER_PORT=8080     # 监听端口
REVERB_APP_ID=your_app_id   # 应用唯一标识
REVERB_APP_KEY=your_app_key # 与前端 Echo 配置一致
REVERB_APP_SECRET=your_app_secret # 安全密钥

3. 启动 Reverb 服务

bash 复制代码
php artisan reverb:start
# 生产环境建议使用守护进程模式
php artisan reverb:start --daemon

4. 创建广播事件

bash 复制代码
php artisan make:event NewMessage

编辑 app/Events/NewMessage.php:

php 复制代码
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class NewMessage implements ShouldBroadcast {
    public $message;

    public function __construct($message) {
        $this->message = $message;
    }

    public function broadcastOn() {
        // 广播到频道 "chat"
        return new Channel('chat');
    }
}

5. 前端订阅(Laravel Echo)

安装 Laravel Echo 和 WebSocket 客户端:

bash 复制代码
npm install --save laravel-echo pusher-js

配置 resources/js/bootstrap.js:

javascript 复制代码
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'reverb',
    key: process.env.MIX_REVERB_APP_KEY,
    wsHost: window.location.hostname,
    wsPort: process.env.MIX_REVERB_PORT || 8080,
    forceTLS: false, // 本地开发禁用 HTTPS
    enabledTransports: ['ws', 'wss'],
});

订阅频道并监听事件:

javascript 复制代码
// 订阅公共频道
Echo.channel('chat')
    .listen('NewMessage', (data) => {
        console.log('收到消息:', data.message);
    });

// 订阅私有频道(需要认证)
Echo.private('chat.${userId}')
    .listen('NewMessage', (data) => { /* ... */ });

6. 触发广播事件

php 复制代码
use App\Events\NewMessage;

// 在控制器或任何地方触发事件
event(new NewMessage('Hello, WebSocket!'));

二、备选方案:Soketi(轻量级 Pusher 替代)

如果你需要更轻量级的解决方案,可以使用 Soketi(兼容 Pusher 协议)。

1. 安装 Soketi

bash 复制代码
npm install -g @soketi/soketi
soketi start --config=soketi.json

2. 配置 Laravel

修改 .env:

env 复制代码
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_app_key
PUSHER_APP_SECRET=your_app_secret
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http  # 生产环境改为 https

3. 前端 Echo 配置

javascript 复制代码
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    wsHost: process.env.MIX_PUSHER_HOST || window.location.hostname,
    wsPort: process.env.MIX_PUSHER_PORT || 6001,
    forceTLS: false,
    enabledTransports: ['ws', 'wss'],
});

三、高级场景:私有频道与认证

1. 频道认证路由

在 routes/channels.php 中定义私有频道授权:

php 复制代码
Broadcast::channel('chat.{userId}', function ($user, $userId) {
    return $user->id === (int) $userId; // 验证用户权限
});

2. 前端订阅私有频道

javascript 复制代码
Echo.private('chat.' + userId)
    .listen('NewMessage', (data) => { /* ... */ });

四、生产环境部署

HTTPS 配置‌:

必须使用 SSL 证书加密 WebSocket(wss://)。

修改前端 Echo 配置中的 forceTLS: true。

javascript 复制代码
window.Echo = new Echo({
    // ...
    forceTLS: true,
    disableStats: true, // 禁用统计
});

Supervisor 守护进程‌(Reverb):

ini 复制代码
[program:reverb]
command=php /path/to/artisan reverb:start --daemon
autostart=true
autorestart=true
stderr_logfile=/var/log/reverb.err.log
stdout_logfile=/var/log/reverb.out.log

五、常见问题排查

连接失败‌:

检查防火墙是否开放端口(8080/6001)。

确认服务正在运行:php artisan reverb:status。

查看日志:tail -f storage/logs/laravel.log。

跨域问题‌:

在 config/cors.php 中允许 WebSocket 域名:

php 复制代码
'paths' => ['api/*', 'broadcasting/*'],
'allowed_origins' => ['https://your-domain.com'],

六、性能优化

Reverb 集群‌:多节点部署时使用 Redis 共享连接状态。

Swoole/Workerman‌:如需更高性能(10万+并发),可集成 Swoole:

bash 复制代码
composer require swooletw/laravel-swoole
php artisan swoole:http start

以上方案覆盖了从开发到生产的完整流程。对于大多数项目,‌Laravel Reverb‌ 是最简单直接的方案;若需要更高灵活性或兼容 Pusher 生态,则选择 ‌Soketi‌。

相关推荐
JaguarJack16 小时前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo16 小时前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack1 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay2 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954482 天前
CTF 伪协议
php
BingoGo5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo6 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack6 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack7 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端