抛出问题
我们发布新版本代码时,如果优雅的终止运行中的异步任务,规避异步任务运行到一半被kill掉的情况。
解决办法
通过调研之后发现,laravel 的 horizon 扩展可以解决这个问题,使用下面的命令可以优雅的结束进程:
- 确保进行中进程不会被kill掉,执行结束后才允许被kill;
- 非进行的任务等候,不会加入到队列中;
优雅的解决了这个问题,思路就是这么的朴实无华。
php artisan horizon:terminate
下面开始隆重介绍 Horizon
简介
Horizon 提供了一个漂亮的仪表盘,可以通过代码配置 Laravel Redis 队列,同时它允许你轻易的监控你的队列系统中诸如任务吞吐量,运行时间和失败任务等关键指标。
安装
注意:确保 queue 配置文件中设置了 redis 队列驱动。
使用 Composer 为 Laravel 项目安装 Horizon:
composer require laravel/horizon
安装完成后,使用 horizon:install 发布 Artisan 命令:
php artisan horizon:install
需要创建 failed_jobs 表,Laravel 将使用该表来存储任何 failed queue jobs:
php artisan queue:failed-table php artisan migrate
升级 Horizon
当准备升级到 Horizon 的一个新的主要版本之前,一定好好看看更新声明,熟悉新特性,结合业务场景思考有没有坑。
注意,升级之后记得要重新发布 Horizon 的资源文件:
php artisan horizon:assets
配置
发布 Horizon 相关文件后,他的主要配置文件会放在 config/horizon.php。
可以在这个文件中配置队列相关选项,并且每个配置项都有详细的使用说明。
注意:确保 horizon 配置文件的 environments 部分包含你计划在其上运行 Horizon 的每个环境的条目。
'environments' => [ 'production' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => [ 'high_{0}', ], 'balance' => 'auto', 'minProcesses' => 1, 'maxProcesses' => 2, 'tries' => 1 ], ], 'test' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => [ 'high_{0}', ], 'balance' => 'auto', 'minProcesses' => 1, 'maxProcesses' => 2, 'tries' => 1 ], ], 'local' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => [ 'high_{0}', ], 'balance' => 'auto', 'minProcesses' => 3, 'maxProcesses' => 11, 'tries' => 1 ], ], ],
均衡配置
Horizon 提供了三种均衡策略: simple , auto ,和 false 。
- 默认的是 simple , 会将收到的任务均分给队列进程:
'balance' => 'simple',
- auto 策略会根据当前的工作量调整每个队列的工作进程任务数量。
例如:如果 A 队列有 1000 个待执行任务,但是你的 B 队列是空的, Horizon 会分配更多的工作进程给 B 队列,直到 A 队列中所有任务执行完成。
- 当配置项 balance 配置为 false ,Horizon 会使用 Laravel 默认执行行为,它将按照配置中列出的顺序处理队列任务。
当使用 auto 策略时,您可以定义 minProcesses 和 maxProcesses 配置选项,以控制最小和最大进程数范围应向上和向下扩展到:
'environments' => [ 'production' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'minProcesses' => 1, 'maxProcesses' => 10, 'tries' => 3, ], ], ],
失败任务记录
horizon 配置文件允许你配置应保留最近和失败任务的时间(以分钟为单位)。 默认情况下,最近的任务保留一小时,而失败的任务保留一周:
'trim' => [ 'recent' => 60, 'failed' => 10080, ], 复制代码
仪表盘权限验证
Horizon 仪表盘路由是 /horizon 。
默认情况下,你只能在 local 环境下访问仪表盘。
在你的 app/Providers/HorizonServiceProvider.php 文件中,有一个 gate 方法。
这里授权控制 非本地 环境中对 Horizon 的访问。
可以根据需要随意修改此门面,以限制对 Horizon 安装的访问:
/** * Register the Horizon gate. * * This gate determines who can access Horizon in non-local environments. * * @return void */ protected function gate() { Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ 'xxxx@xxx.com', ]); }); }
注意:记住,Laravel 会自动将 authenticated 用户注入到 gate 方法。
如果应用程序通过其他方法(如 IP 限制)提供 Horizon 安全,那么 Horizon 用户可能不需要 “登录”。