laravel 5.5 广播(broadcast)的配置及使用

借助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

    

posted @ 2019-12-30 16:51  fogwu  阅读(2318)  评论(0编辑  收藏  举报