需求

给当前在线浏览用户推送优惠券,或者刺激用户消费的话术
今天我们主要是借助Laravel Broadcasting你可以使用上时下很热的Websocket技术

解决方案

1 . 基于laravel的事件广播系统
2 . 基于workman通过长连接
3 . 基于swoole长连接
相同点:三者都可以推送广播事件
区别:1. 事件广播系统更适合局部小范围的laravel项目使用(适合单一用途laravel项目)支持单进程、多线程
workerman则是使用纯php实现的socket框架(适合中小型长连接项目)支持多进程、多线程
swoole是使用C语言实现的socket通信框架(适合大中型长连接项目)支持多进程、多线程

Laravel广播架构

具体流程如下图:

LaravelRedisLaravel Queuelaravel_echo_serverlaravel_echoSend EventRead EventPub Event(Pub/Sub)Listen EventSocket.IoLaravelRedisLaravel Queuelaravel_echo_serverlaravel_echo

图中术语解释:
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订阅服务的订阅者。

根据这幅图我们可以知道事件的广播机制流程:

  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对象

项目的环境

Laravel 5.4.36 (广播机制在 5.4 以后进行了一次重构,并正式加入文档,所以请务必使用 5.4 及其以上版本)
PHP 7.1.13
Redis 3.2.1

广播系统实现

1 .项目构建

composer create-project laravel/laravel laravel --prefer-dist 5.4.*

2 .让Laravel将Event发布到Redis

2.1 打开 config/app.php 找到 ‘provides’ 属性,将 BroadcastServiceProvider 前的注释去掉

App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,

2.2 设置广播路由
打开广播路由配置文件 routes/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;
});Broadcast::channel('news', function ($user, $id) {return true;
});

该channel永远返回true意味着无论收听者是谁,他都会收听到最新的广播。
2.3 设置Redis连接
由于广播机制是基于queue机制实现的。所以queue的存储设置会直接决定广播事件的存储位置。编辑 .env 文件,修改 QUEUE_DRIVER=redis

BROADCAST_DRIVER=redis
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=redis

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

composer require predis/predis

2.4 建立Event
项目根目录执行以下命令,自动生成News Event对象:

php artisan make:event News

app 目录下多出来一个 Events目录,在该目录下产生了广播事件类 News.php
修改app/Events/News.php文件

增加对 ShouldBroadcast 的实现
修改broadcastOn 方法,使用公共广播通道 news
修改构造函数
新增broadcastWith 方法 向客户端推送消息

<?phpnamespace App\Events;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
{use Dispatchable, InteractsWithSockets, SerializesModels;public $message;/*** 创建一个新的事件实例** @return void*/public function __construct($news_message){$this->message = $news_message;}/*** 获取事件广播的频道.** @return \Illuminate\Broadcasting\Channel|array*/public function broadcastOn(){return new Channel('news');// return new PrivateChannel('channel-name');}/*** 获取广播数据** @return array*/public function broadcastWith(){return ['message'=>$this->message];}
}

2.5 新增php artisan命令触发广播事件

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

执行 bignews 命令:

$ php artisan bignews
news sent

通过 redis-cli 查看当前redis中的数据:

127.0.0.1:6379> keys *
1) "queues:default"

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

3 .让Laravel Queue Worker消费Event

如果项目之前没有使用过队列,请去官方文档看一下队列配置
Laravel 的队列系统

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

$ php artisan queue:work

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

php artisan bignews

queue worker的终端界面看到该Event已经被检测到,并通过Redis Sub/Pub机制传播出去了

$ php artisan queue:work
[2019-04-26 01:47:22] Processing: App\Events\News
[2019-04-26 01:47:22] Processed:  App\Events\News

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

127.0.0.1:6379> keys *
1) "queues:default"
127.0.0.1:6379> keys *
(empty list or set)

Laravel Queue Worker连接成功!
接下来我们来让 laravel-echo-server 订阅Redis Sub
4 .让 laravel-echo-server 订阅Redis Sub
4.1 安装

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

全局安装laravel-echo-server

npm install -g laravel-echo-server

4.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://localhost","authEndpoint": "/broadcasting/auth","clients": [],"database": "redis","databaseConfig": {"redis": {},"sqlite": {"databasePath": "/database/laravel-echo-server.sqlite"}},"devMode": false,"host": null,"port": "6001","protocol": "http","socketio": {},"sslCertPath": "","sslKeyPath": "","sslCertChainPath": "","sslPassphrase": "","subscribers": {"http": true,"redis": true},"apiOriginAllow": {"allowCors": false,"allowOrigin": "","allowMethods": "","allowHeaders": ""}
}

devMode 修改为 true
4.3 启动laravel-echo-server

$ laravel-echo-server startL A R A V E L  E C H O  S E R V E Rversion 1.5.0⚠ Starting server in DEV mode...✔  Running at localhost on port 6001
✔  Channels are ready.
✔  Listening for http events...
✔  Listening for redis events...Server ready!

5.laravel-echo收听到广播
5.1 安装laravel-echo

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

$ npm i --save socket.io-client
$ npm i --save laravel-echo

安装laravel-mix:

npm install --save-dev laravel-mix
npm install --unsafe-perm=true --allow-root

5.2 添加测试页面
打开 /resources/assets/js/bootstrap.js 你会发现在这个文件的结尾已经预先写上了 laravel-echo 的使用例子,在文件底部添加如下代码:

import Echo from 'laravel-echo'
window.io = require('socket.io-client');window.Echo = new Echo({broadcaster: 'socket.io',host: window.location.hostname + ':6001'
});

没问题再运行以下命令来编译js,css文件:

npm run dev

这样页面在初始化的时候就会连接上laravel-echo-server。
bootstrap.js 会被 resources/assets/js/app.js 调用。app.js又通过以下引用在页面被调用:

<script src="{{ mix('js/app.js') }}"></script>

修改文件resources/views/welcome.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>BroadcastService</title><link href="{{ mix('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="content" id="app">Broadcast Service
</div>
{{--<script src="{{ asset('./../resources/assets/js/app.js') }}"></script>--}}
<script src="{{ mix('js/app.js') }}"></script>
<script>Echo.channel('news').listen('News', (e) => {console.log(e.message );console.log(e);});
</script>
</body>
</html>

js代码的意思是收听news通道内的News事件对象,将接收到的事件在控制台打印出来

接下来就是访问页面去访问数据了
总共需要开启三个终端:
终端1:启动队列进程

php artisan queue:work

终端2:开启laravel-echo-server服务端服务

laravel-echo-server start

终端3:运行php artisan命令触发广播事件(只是测试使用,项目中根据业务需求直接触发广播事件)

php artisan bignews

好了,去项目首页去测试一下项目广播事件运行如何,这里就自行省略的,如果哪里又不合适的请及时提出,进行改正,也感谢下边这位博主的帮助
参考文章:Laravel Broadcasting广播机制(Redis + socket.io)-学习实例

Laravel 的事件广播系统(Redis驱动)相关推荐

  1. laravel redis_如何将redis优化

    Redis 单线程为什么还能这么快? 因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性 能损耗问题. Redis 单线程如何处理那么多的并发客户端连接? Red ...

  2. 双十一|又快又稳!闲鱼实时事件规则计算驱动平台

    闲鱼双十一金鳞抽奖玩法 相信今年在11月7日-11月11日期间使用过闲鱼的用户,可能已经被如下图所示的幸运海星"砸"到过了.只要用户进入到指定的几个页面,或者在某些指定的页面有点击 ...

  3. 【Laravel Cache】 配置redis 存储缓存,通俗易懂,一次就掌握

    文章目录 1. 配置缓存 /config/cache.php 配置缓存驱动是什么?(即 CACHE_DRIVER="stores 中的key") 配置stores中具体的模块 配置 ...

  4. Laravel event 事件的简单使用

    有时候当我们单纯的看 Laravel手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多加 ...

  5. Android按键事件——上层与驱动的映射

    http://blog.csdn.net/zengdaquan007/article/details/8686431 首先查看android对上层按键事件的定义,在头文件<KeycodeLabe ...

  6. Beetlex之redis驱动

    BeetleX.Redis BeetleX.Redis是基于BeetleX扩展的Redis操作库,全异步操作模式和基于字符缓存策略优化可以提供出色的Redis访问性能:支持SSL,支持读写分离和故障切 ...

  7. .net core redis 驱动推荐,为什么不使用 StackExchange.Redis

    前言 本人从事 .netcore 转型已两年有余,对 .net core 颇有好感,这一切得益于优秀的语法.框架设计. 2006年开始使用 .net 2.0,从 asp.net 到 winform 到 ...

  8. 用.netcore写一个简单redis驱动,调试windows版本的redis

    1. 下载windows版本的redis 2.开发环境vs2017  新建一个 .net core控制台. private static Socket socket = new Socket(Addr ...

  9. laravel 模型事件几种用法

    一 .简单粗鲁(用于本地测试) 路由中定义: Event::listen('eloquent.updated: App\Post',function (){dump('测试一下修改事件'); }); ...

最新文章

  1. 自己动手实现OpenGL之glViewPort(一)
  2. 2019-06-26 某小型支付公司面试经历
  3. css3 选择器_CSS 3
  4. 云原生架构下的持续交付实践
  5. Asp.net 关于错误提示 类型“XXX1”在未被引用的程序集中定义,必须添加对程序集XXX2的引用...
  6. 【图像处理】——Python实现灰度特征提取
  7. 计算机组成原理笔记——存储器分类、层次结构、技术指标、存储单元地址分配
  8. STM32----通用定时器TIM2~TIM5的三种功能
  9. 假的!微信上询问商品会被封号 微信朋友圈公布1月份十大谣言
  10. 【Java】JDK8新特性之函数式接口
  11. BZOJ3211 花神游历各国
  12. 亲,你们都在家办公吗?啥感受?hahaha
  13. 配置阿里云镜像加速器
  14. 用Python带大家写个自动生成艺术签名的小工具哟~
  15. 教师资格证报名网站显示内部服务器错误,2020上半年教师资格考试报名缴费提示错误怎么办?缴费问题汇总...
  16. 转载:js技巧收集(200多个)
  17. 山东大学科技文献期末复习(个人速成向)
  18. opencv拟合多边形
  19. android vrs技术,步步高 vivo V1/Y1 智能手机音质测评报告 VRS[vivo signal
  20. Python实战技巧(11)使用python收发邮件时需要的邮箱授权码如何获取

热门文章

  1. swaggerconfig.java下载_Spring Boot:整合Swagger文档
  2. 一个编程小白的Java SE学习日志 V——类、对象【极客BOY-米奇】
  3. Swift 语言 于 2014 年 9 月 18 日 的 XCode 6.0.1 的更新
  4. time machine无法备份问题
  5. dom、dem、dsm的概念区别
  6. 2021年有限空间作业安全事故总览
  7. erlang NIF部分接口实现(二)类型系统和内存分配接口
  8. 森林防火与林业资源综合解决方案
  9. 【课程设计】教学设备管理系统(源码 + 详解)
  10. 通过rabbitmqadmin管理rabbitmq