魔镜开发日记(二)--laravel+pusher+vue进行websocket即时通讯

项目涉及

魔镜界面上的部分信息需要在某些情况下进行变更,若使用setTimeInterval不断地轮询后台,可行但很明显不是个好的方法。

很自然的就想到了websocket,因为后台已经使用了laravel,laravel的事件广播功能能够帮助实现这一功能。

关于websocket

以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较大。另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一直不返回 Response 给客户端,连接阶段一直是阻塞的。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。和HTTP没什么关系,是基于TCP的一种独立实现。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
websocket

laravel广播系统

介绍

广播系统的目的是用于实现当服务端完成某种特定功能后向客户端推送消息的功能。本文我们将学习如何使用第三方 Pusher 工具向客户端推送消息的功能。

如果您遇到在 Laravel 中需要实现当服务器处理完成某项工作后向客户端发送消息这类的功能,那么您需要使用到 Laravel 的广播系统。

比如在一个支持用户互相发送消息的即时通信应用,当用户 A 给用户 B 发送一条消息时,系统需要实时的将消息推送给用户 B,并且信息以弹出框或提示消息框形式展现给用户 B。

这种使用场景可以完美诠释 Laravel 广播系统的工作原理。另外,本教程将使用 Laravel 广播系统实现这样一个即时通信应用。

或许您会对服务器是如何将消息及时的推送给客户端的技术原理感兴趣,这是因为在服务端实现这类功能时使用了套接字编程技术。在开始实现即时通信系统前,先让我们了解下套接字编程的大致流程:

  • 首先,服务器需要支持 WebSocket 协议,并且允许客户端建立 WebSocket 连接;
  • 您可以实现自己的 WebSocket 服务,或者使用第三方服务如 Pusher,后文会用到 Pusher 库;
  • 客户端创建一个服务器的 Web Socket 连接,连接成功后客户端会获取唯一标识符;
  • 一旦客户端连接成功,表示该客户端订阅了指定频道,将接收这个频道的消息;
  • 最后,客户端还会注册其所订阅的频道的监听事件;
  • 当服务端完成指定功能后,我们以指定频道名称和事件名称的信息通知到 WebSocket 服务器;
  • 最终,WebSocket 服务器将这个指定事件已广播的形式推送到所有注册这个频道监听的客户端。

服务端配置

  • 开启广播服务
    在app.php中取消注释

    1
    2
    // app.php
    App\Providers\BroadcastServiceProvider::class
  • 驱动
    Laravel 自带了几个广播驱动: Pusher 、 Redis , 和一个用于本地开发与调试的 log 驱动。
    项目中使用pusher
    使用composer安装pusher php sdk

    1
    composer require pusher/pusher-php-server "~4.0"

    在pusher官网注册账号,建立项目,获取appid等信息。
    修改广播配置文件,config/broadcasting.php 或者直接修改env文件中pusher的配置信息。

    1
    2
    3
    4
    5
    BROADCAST_DRIVE=pusher
    PUSHER_APP_ID=‘’
    PUSHER_APP_KEY=‘’
    PUSHER_APP_SECRET=‘’
    PUSHER_APP_CLUSTER=‘’
  • 创建广播事件

    1
    php artisan make:event PushAlarmEvent
  • 实现ShouldBroadcast接口

    1
    2
    3
    4
    class PushAlarmEvent implements ShouldBroadcast
    {

    }
  • broadcastOn方法
    ShouldBroadcast 接口要求事件定义一个 broadcastOn 方法。该方法负责指定事件被广播到哪些频道。

    1
    2
    3
    4
    public function broadcastOn()
    {
    return new Channel('alarm‘);
    }
  • 数据
    可以在构造函数中拿数据作为公共属性

  • 授权频道
    在 routes/channe.php参照样例,项目中未涉及

客户端监听

在laravel中可以用laravel-echo,不过魔镜项目是前后端分离的,前端采用的是Vue.

  • 安装pusher-js
1
npm install pusher-js
  • 引入项目
1
import Pusher from ’pusher-js/dist/web/pusher.min'

也可以把这个文件单独拿出来

  • 使用
    1
    2
    3
    4
    5
    6
    7
    8
    var pusher=new Pusher('pusher-key',{
    cluster:'ap3',
    forceTLS:true
    });
    var channel=pusher.subscribe('alarm');
    channel.bind('App\\Events\\PushAlarmEvent',function (data) {
    console.log(data);
    })

结语

于是乎,现在的警报流程变成了

  1. 树莓派向后台请求警报的api
  2. 后台进行相应的处理
  3. 后台通过pusher广播改事件
  4. 前台监听广播事件,做出修改