我们实现的效果为:将一些业务逻辑转化为任务(job),然后启用队列功能,而且是 redis 的队列,同时使用 laravel 官方扩展 Horizon 实现队列的监控。将复杂耗时的工作后台处理,提高前台用户的使用体验。
1. 安装 redis 注意不要使用国内 composer 源,官方的是最全最新的(什么阿里云镜像源反向升级了解一下)
1 composer require predis/predis
修改环境变量 QUEUE_CONNECTION 的值为 redis,并指定我们将使用 predis 作为请求 Redis 的类库:
.env
1 2 3 4 5 6 7 8 . . . QUEUE_CONNECTION=redis REDIS_CLIENT=predis . . .
2. 生成任务类 使用以下 Artisan 命令来生成一个新的队列任务:
1 $ php artisan make:job EnterpriseExport
该命令会在 app/Jobs 目录下生成一个新的类:
app/Jobs/EnterpriseExport.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <?php namespace App\Jobs; use App\Admin\Controllers\Api\StaticFun; use App\Models\Asset; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\DB; class GetAssetsRemainDate implements ShouldQueue, ShouldBeUnique { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * Execute the job. * * @return void */ public function handle() { // 拿到全部资产信息 $assets = Asset::all(); // 开始循环计算资产剩余质保时间并更新 foreach ($assets as $key => $value) { // 计算 $warranty_info = StaticFun::get2DateInfo($value->warranty_start, $value->warranty_end); // 拿取 $warranty_remain = $warranty_info['warranty_remain']; // 更新写入 DB::table('asset')->where('id', $value->id)->update(['warranty_remain' => $warranty_remain]); } } }
还有一点需要注意,我们将会在模型监控器中分发任务,任务中要避免使用 Eloquent 模型接口调用,如:create(), update(), save() 等操作。否则会陷入调用死循环 —— 模型监控器分发任务,任务触发模型监控器,模型监控器再次分发任务,任务再次触发模型监控器… 死循环。在这种情况下,使用 DB 类直接对数据库进行操作即可。
3. 任务分发 前往控制器或者观察者,去插入这项任务。
SettingController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 . . . class SettingController extends Controller { // 展示 public function index(Content $content) { return $content ->header('系统设置') ->description('亲自参与到系统的个性化管理') ->body(function (Row $row) { $row->column(12, Setting::index()); }); } // 刷新资产质保剩余时间 public function warrantyRefresh() { dispatch(new GetAssetsRemainDate); <-- HERE return redirect('/admin/setting'); } } . . .
4. 安装 Horizon 使用 Composer 安装:
1 $ composer require laravel/horizon
安装完成后,使用 vendor:publish Artisan 命令发布相关文件:
1 $ php artisan vendor:publish --provider="laravel\Horizon\HorizonServiceProvider"
分别是配置文件 config/horizon.php 和存放在 public/vendor/horizon 文件夹中的 CSS 、JS 等页面资源文件。
Horizon 是一个监控程序,需要常驻运行,我们可以通过以下命令启动:
至此安装完毕,浏览器打开 larabbs.test/horizon 访问控制台
5. 安装 Supervisor Supervisor 是一个用于 Linux 操作系统的进程监视器。如果 Horizon 进程被退出或终止,Supervisor 将自动重启你的 Horizon 进程。如果要在 Ubuntu 上安装 Supervisor,你可以使用以下命令。如果你不使用 Ubuntu,也可以使用操作系统的包管理器安装 Supervisor:
1 sudo apt-get install supervisor
6. 配置 Supervisor Supervisor 配置文件通常存储在 /etc/supervisor/conf.d 目录下。在此目录中,你可以创建任意数量的配置文件,这些配置文件会告诉 supervisor 如何监视你的进程。例如,让我们创建一个 horizon.conf 文件,它启动并监视一个 horizon 进程:
1 2 3 4 5 6 7 8 9 10 11 12 [program:horizon] process_name=%(program_name)s directory=/data/wwwroot/yanji.wkarrow.top command=/usr/local/php/bin/php artisan horizon autostart=true autorestart=true user=root stopasgroup=true killasgroup=true redirect_stderr=true stdout_logfile=/data/wwwroot/yanji.wkarrow.top/horizon.log stopwaitsecs=3600
注意:要确保 stopwaitsecs 的值大于运行时间最长的任务所消耗的秒数。否则,Supervisor 可能会在工作完成前终止任务。 注意:编辑文件之前,请使用 root 权限进行操作,否则无法保存(针对 homestead 环境下的操作)
7. 启动 Supervisor 在将新代码部署到服务器时,你需要终止 Horizon 主进程,以便进程监视器重新启动它并接收代码的更改。
1 php artisan horizon:terminate
创建了配置文件后,可以使用以下命令更新 Supervisor 配置并启动进程:
1 2 3 4 5 sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start horizon