vue+laravel前后端分离项目中使用laravel-echo

2 篇文章 0 订阅
1 篇文章 0 订阅

系列文章目录

前言

一、环境参数

二、创建项目框架

三、广播架构

你需要了解如下信息:

1.相关信息标识

2.流程架构图及过程:

3.广播事件种类:

四、demo 示例构建

1.假设场景

2.建立广播服务

4.设置Redis连接

5.建立Event

6.测试广播

7.Laravel Queue Worker消费Event

8.laravel-echo-server 订阅Redis Sub

8.1 安装 laravel-echo-server

8.2 初始化

8.3 启动

9.让laravel-echo收听到广播

9.1 安装

9.2 最终效果

总结



前言

        在如今的 web 程序中,WebSockets 被用来实现需要实时、即时更新的接口。当服务器上的数据被更新后,更新信息将通过 WebSocket 连接发送到客户端等待处理。相比于页面使用定时器不停地轮询的程序,WebSocket 是一种更加可靠和高效的选择。

        Laravel通过Broadcasting可以使用如今时下很热的Websocket技术。 Broadcasting允许你在服务端代码和客户端 JavaScript 应用之间共享相同的事件名。

一、环境参数

  • Ubuntu 22.04.1 LTS
  • Redis 6.0.16
  • PHP 7.4.30
  • Laravel 5.6.40 (广播机制在 5.4 以后进行了一次重构,并正式加入文档,所以请务必使用 5.4 及其以上版本)

二、创建项目框架

构建脚手架过程省略...这里主要说明的是使用 laravel-echo demo 

三、广播架构

查阅 技术文档 目前有两种广播机制可供选择:

  • pusher:laravel自带方案,但是有使用限制,需要收费
  • Redis + socket.io:无使用限制

我们使用 第二种 Redis + socket.io 这种方案。

你需要了解如下信息:

1.相关信息标识

  • 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订阅服务的订阅者。

2.流程架构图及过程:

  1. Laravel 通过 broadcasting 机制发布一个Event对象到Redis
  2. Laravel Queue Worker 读取该Event对象,并使用Redis的Sub/Pub机制将该 Event对象发布出去
  3. laravel-echo-server  通过 Redis 的 Sub/Pub机制收听到该 Event
  4. 由于 laravel-echo 使用 socket.io 跟 laravel-echo-server相连接。所以 laravel-echo 会通过socket.io将Event对象发送给laravel-echo
  5. laravel-echo解析通过 socket.io接收到的 Event对象

3.广播事件种类:

  • public:谁都可以收听的广播
  • private:只有指定用户可以收到的广播
  • presence:不仅可以收听到跟你有关的广播,还可以跟别的用户互动,适合做聊天室

四、demo 示例构建

1.假设场景

假设我们要使用laravel作为服务端做一个新闻推送系统。用户打开页面后不需要刷新页面即可不断的获取到最新的新闻。

2.建立广播服务

注册 BroadcastServiceProvider,打开 config/app.php 找到 'provides' 属性,将 BroadcastServiceProvider 前的注释去掉,如下代码示例(app.php 部分代码):

/*
  * Application Service Providers...
*/
   App\Providers\AppServiceProvider::class,
   App\Providers\AuthServiceProvider::class,
   App\Providers\BroadcastServiceProvider::class,
   App\Providers\EventServiceProvider::class,
   App\Providers\RouteServiceProvider::class,

3.设置广播路由

打开广播路由配置文件 routes/channels.php 。该文件用来确定广播事件的流向,在presence广播中还肩负着补充事件内容的工作。我们在 channels.php 中增加一个新的广播通道 news

<?php

/*
|--------------------------------------------------------------------------
| Broadcast Channels
|--------------------------------------------------------------------------
|
| Here you may register all of the event broadcasting channels that your
| application supports. The given channel authorization callbacks are
| used to check if an authenticated user can listen to the channel.
|
*/

Broadcast::channel('App.User.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});

// 该channel永远返回true意味着无论收听者是谁,他都会收听到最新的广播。
Broadcast::channel('news_test', function () {
    return true;
});

4.设置Redis连接

由于广播机制是基于queue机制实现的。所以queue的存储设置会直接决定广播事件的存储位置。编辑 .env 文件,修改 QUEUE_DRIVER = redis

QUEUE_DRIVER=redis

5.建立Event

php artisan make:event News

项目根目录下的 app 文件夹中会多出来一个 Events目录,该目录下产生了广播事件类 News.php文件。

针对刚生成News类进行如下修改:

  • 增加对 ShouldBroadcast 的实现
  • 修改broadcastOn 方法,使用公共广播通道 news_test
  • 修改构造函数
<?php

namespace App\Events;

use Carbon\Carbon;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class News implements ShouldBroadcast  // 1. 事件是要广播出去的
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($news_message)  // 2.广播出去的内容
    {
        //
        $this->message = $news_message;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()  // 3.对那些频道进行广播
    {
        // 创建频道
        return new Channel('news_test');
        // return new PrivateChannel('channel-name');
    }

      /**
       *  指定广播数据
      */
//    public function broadcastWith()
//    {
//
//        // 返回当前时间
//        return ['name' => Carbon::now()->toDateString(),'message'=> $this->message];
//
//    }
}

6.测试广播

为项目增加 predis依赖,在项目根目录下执行:

composer require predis/predis

检测执行完后 composer.json 中增加了 predis 的依赖

"require": {
    "php": "^7.4.3",
    "darkaonline/l5-swagger": "5.6.*",
    "fideloper/proxy": "^4.0",
    "guzzlehttp/guzzle": "^7.4",
    "laravel/framework": "5.6.*",
    "laravel/tinker": "^1.0",
    "predis/predis": "1.1",
    "spatie/laravel-permission": "~2.7",
    "ext-json": "*"
},

新增一个artisan命令来测试是否可以将广播发送到 Redis中,编辑 routes/console.php ,增加 bignews 命令。

Artisan::command('bignews', function () {
 
    broadcast(new News(date('Y-m-d h:i:s A').": BIG NEWS!")); 
    $this->comment("news sent");

})->describe('这是一个news 测试');

执行 bignews 命令:

$ php artisan bignews

$ news sent

通过 redis-cli 查看当前redis中的数据,发现多出来一个queue对象

127.0.0.1:6379> keys *

1) "queues:default"

到此 Laravel的广播机制就成功的连接上了 Redis!

7.Laravel Queue Worker消费Event

新开一个终端窗口,并在根目录下启动 Laravel Queue Worker

php artisan queue:work

之前的终端窗口,再广播一个news Event:

php artisan bignews

你可以在queue worker的执行界面看到该Event已经被检测到,并通过Redis Sub/Pub机制传播出去了

$ php artisan queue:work
$ [2018-05-25 23:24:03][OvuviSKDpM9R5LrIilBEgSLcDpk3hDXc] Processing:
 App\Events\News

还记得之前通过Laravel广播事件之后redis中会产生一个 queue:default对象么?这次如果你快速的通过 keys * 命令查询redis中的对象,你会发现 queue:default 每次被产生出来就会迅速的被 queue worker消费掉

  1. 127.0.0.1:6379> keys *

  2. 1) "queues:default"

  3. 127.0.0.1:6379> keys *

  4. (empty list or set)

Laravel Queue Worker连接成功!

8.laravel-echo-server 订阅Redis Sub

8.1 安装 laravel-echo-server

如果使用pusher那么直接使只用laravel就可以了,如果使用 Redis + socket.io 则需要使用开源项目 laravel-echo-server 。所以我们现在要使用 laravel-echo-server。

再新开一个终端窗口。由于我们之前已经开了两个终端窗口了,所以这是第三个终端窗口。

先切换到root用户,然后安装laravel-echo-server

npm install -g laravel-echo-server

8.2 初始化

我们切换到项目根目录下,初始化 laravel-echo-server,所有问题都使用默认配置:

$ laravel-echo-server init

? Do you want to run this server in development mode? No

? Which port would you like to serve from? 6001

? Which database would you like to use to store presence channel members? redis

? Enter the host of your Laravel authentication server. http://localhost

? Will you be serving on http or https? http

? Do you want to generate a client ID/Key for HTTP API? No

? Do you want to setup cross domain access to the API? No

Configuration file saved. Run laravel-echo-server start to run server.

它会帮你在项目根目录下生成 laravel-echo-server.json 配置文件,默认配置(下面我已经改过)为

{
	"authHost": "http://127.0.0.1:8644",
	"authEndpoint": "/broadcasting/auth",
	"clients": [],
	"database": "redis",
	"databaseConfig": {
		"redis": {},
		"sqlite": {
			"databasePath": "/database/laravel-echo-server.sqlite"
		}
	},
	"devMode": true,
	"host": "127.0.0.1",
	"port": "6001",
	"protocol": "http",
	"socketio": {},
	"secureOptions": 67108864,
	"sslCertPath": "",
	"sslKeyPath": "",
	"sslCertChainPath": "",
	"sslPassphrase": "",
	"subscribers": {
		"http": true,
		"redis": true
	},
	"apiOriginAllow": {
		"allowCors": false,
		"allowOrigin": "",
		"allowMethods": "",
		"allowHeaders": ""
	}
}

8.3 启动

执行以下命令启动 laravel-echo-server

$ laravel-echo-server start

成功启动后会输出以下日志

 我们再回到第一个终端窗口,再次广播一个news Event。你会发现 laravel-echo-server 会输出以下日志

 laravel-echo-server连接成功!

因为laravel-echo-server使用的是 6001 端口,所以记得去 Nginx 里面添加6001 端口的映射

注意: 小编就是因为这边之前没有走通

在 /etc/nginx/conf.d/8644.conf (该项目配置路径)里面编辑 填加如下代码

...
  location ~/socket.io {
         proxy_pass http://localhost:6001;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "Upgrade";
    }
...

添加完后记得重启 nginx 

9.让laravel-echo收听到广播

9.1 安装

由于前端使用的是 laravel-echo来收听广播,我们选择的底层实现方式是socket.io。所以首先我们要在package.json中添加 laravel-echo 和 socket.io的依赖

$ npm i --save socket.io-client@^2.2.0

$ npm i --save laravel-echo@^1.5.2

跟 main.js 同级创建 bootstrap.js并编辑

import Echo from 'laravel-echo'

window.io = require('socket.io-client')
window.Echo = new Echo({
  broadcaster: 'socket.io',
  host: 'http://127.0.0.1:8101'
  // auth: {
  //   headers: {
  //     Authorization: 'Basic NDAxX0NkcVc6NDAxX0R1YTYza3JS'
  //   }
  // }
})

// // 测试
window.Echo.channel('news_test').listen('News', (e) => {
  console.log('1111111111111111')
  console.log(e)
})

在 main.js中 引入,如下:

require('./bootstrap')
import Vue from 'vue'

import Cookies from 'js-cookie'

import 'normalize.css/normalize.css' // a modern alternative to CSS resets

import Element from 'element-ui'
import './styles/element-variables.scss'
...

 然后运行前端vue 代码 

npm run dev

9.2 最终效果

后端监控

前端接受 


总结

 以上就是今天要讲的内容,本文仅仅简单介绍了 vue+laravel前后端分离项目中使用laravel-echo的使用,而利用WebSocket 是一种更加可靠和高效的选择。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坏小子小幺儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值