Laravel进阶系列笔记--(八)Laravel 基于Reids的消息队列的使用
作者:温新
时间:2021-07-09
hi,我是温新,一名PHPer。
本篇文章紧接着 Laravel进阶系列笔记--(7)Laravel 基础数据库存储的消息队列的使用 篇文章,两篇文章之前的关系是紧密相连,同时,本篇 Redis消息队列的使用 是基于该篇的操作进行的。
基于Redis的队列任务
第一步:windows下安装Redis数据库与Redis扩展
关于Redis的安装请自行安装。
第二步:修改驱动为Redis
文件:.env
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 修改redis驱动</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">QUEUE_CONNECTION</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">redis</span></span>
只要把驱动修改为
redis
,其他的什么都不要动。没错,就是这样的简单,这样的优雅。
修改为Redis
驱动,windows中打开Redis服务器与客户端。
第三步:创建任务类
php artisan make:job SendEamilToUser
该命令会在
app/Jobs
目录下生成SendEamilToUser.php
文件。
编辑SendEamilToUser.php
文件进行消息队列任务的处理
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">namespace</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">App\Jobs</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">App\Models\User</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Bus\Queueable</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Queue\ShouldBeUnique</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Queue\ShouldQueue</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Foundation\Bus\Dispatchable</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Queue\InteractsWithQueue</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Queue\SerializesModels</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Support\Facades\Log</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">SendEamilToUser</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">implements</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">ShouldQueue</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Dispatchable</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">InteractsWithQueue</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Queueable</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">SerializesModels</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$user</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">null</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">__construct</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">User</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$user</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">user</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$user</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">handle</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 此处执行自定义任务</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Log</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">info</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'发送邮件给 【'</span> . <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">user</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">name</span> . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'】 用户成功'</span> );</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>
第四步:派发任务给队列
1)定义路由
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// web.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Route</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">get</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'queue'</span>, <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'UserController@queue'</span>);</span>
2)添加queue
方法并编写任务代码
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// UserController.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">App\Jobs\SendEamilToUser</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">queue</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$users</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">\App\Models\User</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">all</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">foreach</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$users</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">as</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$user</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 为每个用户发送消息的任务</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 方式一</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">//dispatch(new SendEamilToUser($user));</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 方式二</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">SendEamilToUser</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">dispatch</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$user</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'派发队列任务成功'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>
打开
jobs
数据表就会看到相关的任务信息了。
3)访问路由添加队列任务
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 添加队列任务完成后,通过redis客户端进行查看。</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(17, 102, 68)">127.0</span>.<span style="box-sizing: border-box;color: rgb(17, 102, 68)">0.1</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">6379</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">></span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">keys</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">*</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>) <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"laravel_database_queues:default:notify"</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(17, 102, 68)">2</span>) <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"laravel_database_queues:default"</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(17, 102, 68)">127.0</span>.<span style="box-sizing: border-box;color: rgb(17, 102, 68)">0.1</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">6379</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">></span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">type</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">laravel_database_queues</span>:<span style="box-sizing: border-box;color: rgb(119, 0, 136)">default</span>:<span style="box-sizing: border-box;color: rgb(0, 0, 0)">notify</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">list</span></span>
第五步:执行队列任务
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 执行所有任务</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">artisan</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">queue</span>:<span style="box-sizing: border-box;color: rgb(0, 0, 0)">work</span></span>
第六步:查询日志文件
<span style="box-sizing: border-box;padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(17, 102, 68)">2021</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-</span><span style="box-sizing: border-box;color: rgb(17, 102, 68)">07</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-</span><span style="box-sizing: border-box;color: rgb(17, 102, 68)">09</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">13</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">35</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">43</span>] <span style="box-sizing: border-box;color: rgb(0, 0, 0)">local</span>.<span style="box-sizing: border-box;color: rgb(0, 0, 0)">INFO</span>: <span style="box-sizing: border-box;color: rgb(0, 0, 0)">发送邮件给</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">【Dell</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Terry】</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">用户成功</span> </span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(17, 102, 68)">2021</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-</span><span style="box-sizing: border-box;color: rgb(17, 102, 68)">07</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-</span><span style="box-sizing: border-box;color: rgb(17, 102, 68)">09</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">13</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">35</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">43</span>] <span style="box-sizing: border-box;color: rgb(0, 0, 0)">local</span>.<span style="box-sizing: border-box;color: rgb(0, 0, 0)">INFO</span>: <span style="box-sizing: border-box;color: rgb(0, 0, 0)">发送邮件给</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">【Thomas</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Bruen】</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">用户成功</span> </span>
如此,任务完成。
有没有注意到一个问题,要查看队列任务很不方便,与数据库相比,可观性太差了。好在,Laravel官方提供了Horizon
扩展包解决了此问题。
可视化的Horizon队列系统解决方案
使用Horizon
第一步:安装Horizon
composer require laravel/horizon
报错: Install or enable PHP's pcntl extension.的解决方法
由于是在windows中,可能会报相关扩展的错误,错误如下:
- laravel/horizon[v5.7.0, ..., 5.x-dev] require ext-pcntl * -> it is missing from your system. Install or enable PHP's pcntl extension.
- Root composer.json requires laravel/horizon ^5.7 -> satisfiable by laravel/horizon[v5.7.0, ..., 5.x-dev].
解决方法如下:
1)打开composer.json
文件,添加如下配置
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"platform": {
"ext-pcntl": "7.2",
"ext-posix": "7.2"
}
},
2)安装
composer install
3)重新安装Horizon
第二步:发布资源并生成配置配置文件
php artisan horizon:install
config
目录下生成horizon.php
配置文件
第三步:访问后台
可以通过horizon
路由对队列后台进行访问。
可以看到状态是Inactive
未启动的状态,下面开始启动
第四步:运行Horizon
php artisan horizon
使用 php artisan horizon 报错:Call to undefined function Laravel\Horizon\Console\pcntl_async_signals()
很遗憾,pcntl
扩展安装失败,虽然第一步的报错解决,显示也是安装成功,但是确实没有安装上。windows对此支持很是不友好,第四步无法执行成功。
windows下我没有找到解决方法,因此使用终端进行监控。
// 终端监控
php artisan queue:listen
到此使用horizon完毕
Horizon其他命令
暂停horizon
php artisan horizon:pause
继续horizon
php artisan horizon:continue
查看horizon状态
php artisan horizon:status
优雅的终止horizon
php artisan horizon:terminate
该命令会在所有当前正在执行的任务执行完成后退出horizon.
关于horizon
还有一些其他的使用,请参考官方访访文档。
消息队列篇--完。
我是温新
每天进步一点点,就一点点