借助Laravel Broadcasting你可以使用上时下很热的Websocket技术。
注意:请务必使用较新版本的 Laravel。Laravel在最近几个版本进行过比较大的重构,比如路由从 app\Http\routes.php 拆分为到 routes 目录下的多个文件,包括广播在内的各个附加组件也都进行了重构并正式写入文档。所以网上有些教程(特别是入门教程)可能是根据旧版本来写的,容易让你迷惑。当安装完Laravel后执行以下命令查看Laravel版本
php artisan --version
如果低于 5.4 请重新建立新版本的Laravel,具体方法在下面会详细讲解。
实例背景:
假设场景:
假设我们要使用laravel作为服务端做一个新闻推送系统。用户打开页面后不需要刷新页面即可不断的获取到最新的新闻。
环境参数
Homestead 7.4.2
Laravel 5.5 (广播机制在 5.4 以后进行了一次重构,并正式加入文档,所以请务必使用 5.4 及其以上版本)
PHP 7.1
Redis 4.0.9 (Homestead 自带redis)
————————————————
广播架构
目前有两种广播机制可选:
pusher:laravel自带方案,但是有使用限制,需要收费
Redis + socket.io:无限制
我们使用业界较流行的Redis + socket.io 方案 。
接下来你会信息爆炸似的接收到好几个新名词:
laravel-echo-server:使用 socket.io 机制实现的 broadcasting 服务端
laravel-echo:laravel-echo是 laravel broadcasting 的客户端。注意,laravel-echo 并不是 laravel-echo-server 专属的客户端, laravel-echo 有两种连接机制可以选:pusher 和 socket.io 。 而 laravel-echo-server 是开发出来专门用于 socket.io连接的服务端。如果你使用的是 pusher,那么不需要使用 laravel-echo-server ,但是你依然要使用 laravel-echo
Socket.IO:websocket 的一种nodejs实现。laravel-echo 如果要使用socket.io 则需要先安装 socket.io-client。
Predis:redis客户端的php实现,如果要使用redis作为广播机制的实现,则需要先安装 predis
Laravel Event:广播事件类
Laravel Queue:广播机制是基于queue机制来实现的
Redis Sub/Pub:Redis的订阅机制。laravel-echo-server本质上只是一个Redis订阅服务的订阅者。
这几样东西配合起来的架构图如下
根据这幅图我们可以知道事件的广播机制流程:
Laravel 通过 broadcasting 机制发布一个Event对象到Redis
Laravel Queue Worker 读取该Event对象,并使用Redis的Sub/Pub机制将该 Event对象发布出去
laravel-echo-server 通过 Redis 的 Sub/Pub机制收听到该 Event
由于 laravel-echo 使用 socket.io 跟 laravel-echo-server相连接。所以 laravel-echo 会通过socket.io将Event对象发送给laravel-echo
laravel-echo解析通过 socket.io接收到的 Event对象
广播事件种类:
public:谁都可以收听的广播
private:只有指定用户可以收到的广播
presence:不仅可以收听到跟你有关的广播,还可以跟别的用户互动,适合做聊天室
我们假设的场景是新闻推送系统,所以使用最简单的public广播就可以实现。接下来我们详细的来讲解如何将这些组件配置好,并连接起来。
我们按照广播机制的流程来一步一步的设置广播机制。
1、注册 BroadcastServiceProvider,打开 config/app.php 找到 ‘provides‘ 属性,将 BroadcastServiceProvider 前的注释去掉
2、安装redis(不改动的情况下安装好后redis使用默认即可)
composer required predis/predis
3、配置.env文件
由于广播机制是基于queue机制实现的。所以queue的存储设置会直接决定广播事件的存储位置 BROADCAST_DRIVER=redis 设置queue为redis QUEUE_DRIVER=redis
4、建立事件(event)
php artisan make:event loginLogEvent
修改事件源码增加广播频道:
/*增加对 ShouldBroadcast 的实现*/ class loginLogEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $message; /** * Create a new event instance. * * @return void */ public function __construct($news_message) { $this->message = $news_message; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new Channel(‘loginLogEvent‘); } }
5、增加广播路由(routes\channels.php)
/*channel 方法接收两个参数:频道名称和一个回调函数,该回调通过返回 true 或者 false 来表示用户是否被授权监听该频道*/ Broadcast::channel(‘loginLogEvent‘,function ($user,$id) { return true; });
6、测试广播:
1)编辑 routes/console.php ,增加 bignews 命令:
/*自定义命令*/ Artisan::command(‘bignews‘, function () { broadcast(new loginLogEvent(date(‘Y-m-d h:i:s A‘).": BIG NEWS!")); $this->comment("news sent");})->describe(‘Send news‘);
2)测试命令:
输入:php artisan bignews
通过 redis-cli 查看当前redis中的数据,发现多出来一个queue对象,证明连接成功了,如果没有,请检查env配置中的queue配置是否正确
你还你可以在queue worker的执行界面看到该Event已经被检测到,并通过Redis Sub/Pub机制传播出去了
7:安装并配置 laravel-echo-server
1)安装
npm install -g laravel-echo-server
2)初始化 Socket 服务(切记在生产环境中,无论你什么时候使用它,都应该关掉你的开发者模式)
laravel-echo-server init
它会帮你在项目根目录下生成 laravel-echo-server.json
3)启动laravel-echo-server
启动/停止 laravel-echo-server start/stop
启动后,在新打开一个终端窗口,输入 php artisan bignews 显示如下证明广播推送到了laravel-echo-server
8:端口映射:
因为laravel-echo-server使用的是 6001 端口,所以记得去 Homestead.yaml里面添加6001 端口的映射
使用命令:vagrant reload 重载生效
9、浏览器收听广播
1)安装组件
/*由于前端使用的是 laravel-echo来收听广播,我们选择的底层实现方式是socket.io。所以首先我们要在package.json中添加 laravel-echo 和 socket.io的依赖*/ npm i --save laravel-echo npm i --save socket.io-client
2)配置/resources/assets/js/bootstrap.js
import Echo from ‘laravel-echo‘ /*使用 pusher window.Pusher = require(‘pusher-js‘); window.Echo = new Echo({ broadcaster: ‘pusher‘, key: ‘your-pusher-key‘, cluster: ‘mt1‘, encrypted: true }); */ /*使用 socket.io-client*/ window.io = require(‘socket.io-client‘); window.Echo = new Echo({ broadcaster: ‘socket.io‘, host:window.location.hostname+‘:6001‘ });
3) 重新编译app.js 文件
注意:*默认使用 http:
//registry.npmjs.org在国内不稳定,如果出现404错误,可切换使用国内镜像*
npm config set registry=
https://registry.npm.taobao.org
npm run dev
4) 建立测试文件
在resources\views\目录下新建boradcast.blade.php 文件,放入以下内容
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>News Room</title> <link href="{{ mix(‘css/app.css‘) }}" rel="stylesheet"> </head> <body> <div class="content"> News Room </div> <script src="{{ mix(‘js/app.js‘) }}"></script> <script> /*收听loginLogEvent通道内的loginLogEvent事件对象,将接收到的事件在控制台打印出来。*/ Echo.channel(‘loginLogEvent‘) .listen(‘loginLogEvent‘, (e) => { alert(JSON.stringify(e)); console.log(e.message); }); </script> </body>
5)在rotues/web.php 加入路由路径
Route::view(‘broadcast‘,‘boradcast‘);
6)查看效果
启动步骤:打开一个命令窗口启动 : laravel-echo-server start
再打开一个窗口启动队列启动队列: php artisan queue:work
给队列加内容: php artisan bignews
参考:https://blog.csdn.net/nsrainbow/article/details/80428769
原文地址:https://www.cnblogs.com/fogwang/p/12112265.html