启动 Laravel Echo Server
上篇教程我们完成了广播系统的后端配置和事件分发,并探究了底层源码的实现,最终落地的都是通过 Redis 发布命令发布消息。
接下来我们需要借助 Laravel Echo Server 搭建起 Websocket 服务器,这里面除了封装 Socket.io 服务端之外,还包含了订阅服务端广播频道的 Redis 客户端,用于接收服务端 Redis 发布的消息,再通过 Socket.io 广播给客户端。
如果是在本地搭建,按照 Laravel Echo Server 文档给出的安装和启动步骤操作即可,如果使用的是 Laradock,其内置了 laravel-echo-server
这个容器服务配置,使用 docker-compose up -d laravel-echo-server
启动即可,如果使用的是 Laravel Sail 作为本地开发环境,可以参考 Laradock 提供的 laravel-echo-server
编排配置引入它。
通过 Sail 编排 Laravel Echo Server
在项目根目录的 docker
目录下(我已经通过 sail artisan sail:publish
发布了 Sail 的容器编排文件,所有会有这个目录)新建一个 laravel-echo-server
子目录,然后把 laradock/laravel-echo-server
目录下的所有文件拷贝到这个子目录下:
修改 laravel-echo-server.json
配置如下:
{
"authHost": "redis.test",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "redis"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "redis.test",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
在项目根目录下 docker-compose.yml
的 services
中新增一个 laravel-echo-server
服务编排配置:
services:
...
laravel-echo-server:
build:
context: ./docker/laravel-echo-server
dockerfile: Dockerfile
args:
- CHANGE_SOURCE=${CHANGE_SOURCE}
volumes:
- ./docker/laravel-echo-server/laravel-echo-server.json:/app/laravel-echo-server.json:ro
ports:
- "${LARAVEL_ECHO_SERVER_PORT}:6001"
depends_on:
- redis
networks:
- sail
在 .env
中新增两个配置项:
CHANGE_SOURCE=true
LARAVEL_ECHO_SERVER_PORT=6001
然后就可以通过如下命令启动 Laravel Echo Server 容器服务了:
代码语言:javascript复制sail up -d
初次构建会先拉取 laravel-echo-server
的容器镜像。启动完成后,就可以通过 sail ps
命令查看它是否启动成功:
或者通过查看 laravel-echo-server
日志也可以确认它是否启动成功:
Laravel Echo 客户端
启动好 Laravel Echo Server 后,接下来,我们来安装配置 Laravel 官方提供的广播客户端前端库 Laravel Echo,它既支持 Pusher,也支持 Socket.io,这里我们肯定需要通过 Socket.io 客户端进行通信了。
由于我们上篇教程已经在项目中安装过 socket.io-client
,所以只需要单独安装 laravel-echo
即可,不过需要把 package.json
中已安装的 socket.io-client
版本调整为与 laravel-echo-server
中的 socket.io
版本一致,否则很可能导致 Websocket 连接建立失败(学院君就遇到了这个问题,折腾了半天,网上也没啥靠谱的答案,最后灵感突发,猜测是不是客户端与服务端版本不一致引起的,最后验证了下还真是,目前这个版本号是 2.3.0
,将 socket.io-client
版本号调整为 ^2.3.0
即可):
npm install --save laravel-echo
然后在 resources/js/bootstrap.js
中取消 Laravel Echo 相关代码前面的注释,并将 Pusher 客户端实现调整为 Socket.io 客户端:
import Echo from 'laravel-echo';
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname ':6001'
});
window.Echo.channel('laravel_database_test-channel').listen('UserSignedUp', event => {
console.log(event.user);
});
运行 sail npm run dev
编译前端代码让上述修改生效。
至此,我们就将前面基于 Redis Socket.io 原生代码实现的事件广播功能重构为了基于 Laravel 广播组件 Laravel Echo Server Laravel Echo 实现的完整广播系统了,这样一来,我们就可以使用 Laravel 广播系统提供的所有功能了,包括事件广播的推送和接收、私有频道、存在频道等。
不过在此之前,我们还是验证下这个广播系统是否可以正常工作。
验证 Laravel 事件广播消息推送
在访问 /broadcast
路由前,还需要在 resources/views/websocket.blade.php
的 <head>
标签中添加获取 CSRF 令牌的代码以便被 Laravel Echo 读取:
<meta name="csrf-token" content="{{ csrf_token() }}">
在浏览器中访问 http://redis.test/broadcast
,此时服务端还没有推送事件广播消息,但是可以在 laravel-echo-server
日志中看到 Websocket 客户端信息,joined
表示客户端与服务端建立连接,left
表示客户端断开连接,之所以出现下面这个 joined-left-joined
日志,是因为我刷新过 /broadcast
页面:
在浏览器中也可以在开发者工具中看到熟悉 Socket.io Websocket 连接成功消息流:
接下来,我们运行如下 Artisan 命令分发事件广播:
代码语言:javascript复制sail artisan redis:publish
然后启动队列处理器进程处理 broadcast
队列消息(这一步也不能漏了哈,因为 Laravel 默认是基于消息队列处理广播消息的):
sail artisan queue:work --queue=broadcast
这个时候,查看 laravel-echo-server
的日志,就可以看到服务端发布的事件消息已经被 Laravel Echo Server 中的 Redis 接收处理了:
底层原理和我们通过 Redis Socket.io 原生代码实现广播功能是一样的,基于 Redis 订阅功能实现,感兴趣的同学可以去看下 Laravel Echo Server 实现源码。
在浏览器页面开发者工具的 Console
中,也可以看到客户端接已经收到这个事件消息并打印出用户信息来了:
至此,从 Laravel 服务端到 Laravel Echo Server 到 Laravel Echo 客户端的广播链路就已经打通了。
本系列教程首发在学院君网站(xueyuanjun.com),你可以点击页面左下角阅读原文链接查看最新更新的教程。