仪表盘【不适用于 Windows】
仪表盘就是 Horizon 咯
安装
composer require laravel/horizon
配置
发布相关文件(包含配置等)
php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
参考:Horizon - 配置 |《Laravel 5.5 中文文档》 | PHP / Laravel 社区文档
开始使用
连接/驱动
根据 config/queue.php
文件,我们了解到驱动的配置在项目根目录 .env
文件内
打开 .env
文件,可将 QUEUE_DRIVER
设置为 QUEUE_DRIVER=redis
,其下方为 Redis 连接基本配置
# 连接地址
REDIS_HOST=127.0.0.1
# 连接密码
REDIS_PASSWORD=
# 连接端口
REDIS_PORT=6379
在 config/database.php
中最下方,我们可以看到 Redis 的默认配置,建议将 database
部分修改为:
'database' => env('REDIS_DB_SELECT', 0)
然后在 .env
文件的 Redis 连接部分下添加一行,Like this。(这样我们可以直接指定其它的 DB)
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=
REDIS_PORT=6379
REDIS_DB_SELECT=0
差点忘了,Redis 需要安装依赖
composer require predis/predis
创建任务类
项目根目录执行
php artisan make:job BaseJob
然后在 app\Jobs
目录下得到 BaseJob.php
文件
其中 handle()
方法在队列任务执行触发
添加任务到队列
我们在一个测试用的控制器里面写一个 queue()
方法。
对于测试控制器,路由部分我是这么玩儿的
-
app\Http\Controllers
下创建TestController
控制器 routes\web.php
内添加
Route::any('/test/{action?}', function ($action = '') {
return App::make("App\Http\Controllers\TestController")->$action();
});
- 这样就可以直接访问
localhost/test/方法名
,如果按照我的方法就是这样的:localhost/test/queue
我们继续完善这个方法:
public function queue() {
// 可以瞧瞧返回值,记得 use App\Jobs\BaseJob;
var_dump(BaseJob::dispatch());
}
切换到 app\Jobs\BaseJob.php
文件,在 handle()
方法里面添加一点输出内容:
public function handle() {
echo "job executed\n";
$this->delete();
}
至此一个简单的队列就完成了,接下来让我们运行它。
发布任务、执行任务
我们直接请求 http://localhost/test/queue【地址自己替换一下】,将任务发布到 Redis 里面,页面上返回结果如下:
object(Illuminate\Foundation\Bus\PendingDispatch)[467]
protected 'job' =>
object(App\Jobs\BaseJob)[463]
public 'tries' => int 3
public 'timeout' => int 60
private 'type' => null
private 'data' =>
array (size=0)
empty
protected 'job' => null
public 'connection' => null
public 'queue' => null
public 'chainConnection' => null
public 'chainQueue' => null
public 'delay' => null
public 'chained' =>
array (size=0)
empty
需要了解的是,这个任务我们并没有指定队列名称,所以它使用的是默认队列名称 default
,我们通过一些 Redis GUI 软件可以看到任务详情。
当然这不重要,Redis 里面的数据表示任务已经添加到队列中了,接下来只需要执行这个任务就行。在项目根目录戳如下命令:
# --once 表示执行一次,如果不添加 --once 参数,该命令会持续监听队列。如需终止,请按 Ctrl+C/control+C
php artisan queue:work --once
命令行会返回如下内容:
[2018-10-25 18:18:32] Processing: App\Jobs\BaseJob
job executed
[2018-10-25 18:18:32] Processed: App\Jobs\BaseJob
至此一个简单的队列任务添加、发布、执行就完成了。
更多使用姿势
传递自定义数据
我们将 queue()
方法改成如下内容:
var_dump(BaseJob::dispatch(['name' => 'Max Sky', 'gender' => 1])
->onQueue('MyQueue'));
此处我们在 dispatch
方法内放入了一个数组,该数组在任务执行时可得到并使用;onQueue
方法指定了一个队列名称。
回到 BaseJob.php
,调整构造函数如下:
private $data;
public function __construct($data = []) {
$this->data = $data;
}
修改 handle()
方法如下:
public function handle() {
print_r($this->data);
$this->delete();
}
好了,让我们刷新一下网页 http://localhost/test/queue
结果已经有了变化:
object(Illuminate\Foundation\Bus\PendingDispatch)[467]
protected 'job' =>
object(App\Jobs\BaseJob)[463]
public 'tries' => int 3
public 'timeout' => int 60
private 'type' => null
private 'data' =>
array (size=2)
'name' => string 'Max Sky' (length=7)
'gender' => int 1
protected 'job' => null
public 'connection' => null
public 'queue' => string 'MyQueue' (length=7)
public 'chainConnection' => null
public 'chainQueue' => null
public 'delay' => null
public 'chained' =>
array (size=0)
empty
队列名称和自定义数据都显示出来了。
Redis 中有了新的队列名称 Key
Value 部分看起来是这样的:
{
"displayName": "App\Jobs\BaseJob",
"job": "Illuminate\Queue\CallQueuedHandler@call",
"maxTries": 3,
"timeout": 60,
"timeoutAt": null,
"data": {
"commandName": "App\Jobs\BaseJob",
"command": "O:17:\"App\Jobs\BaseJob\":11:{s:5:\"tries\";i:3;s:7:\"timeout\";i:60;s:23:\"\u0000App\Jobs\BaseJob\u0000type\";N;s:23:\"\u0000App\Jobs\BaseJob\u0000data\";a:2:{s:4:\"name\";s:7:\"Max Sky\";s:6:\"gender\";i:1;}s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";s:7:\"MyQueue\";s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:5:\"delay\";N;s:7:\"chained\";a:0:{}}"
},
"id": "1",
"attempts": 0,
"type": "job",
"tags": [],
"pushedAt": 1540464437.013529
}
然后我们再试试执行这个任务:
php artisan queue:work --once
咦?什么都没有发生。。。因为我们指定了队列名称,所以在执行的时候也必需指定:
php artisan queue:work --once --queue=MyQueue
返回结果如下,可以发现自定义的数据被传递进来:
[2018-10-25 18:53:08] Processing: App\Jobs\BaseJob
Array
(
[name] => Max Sky
[gender] => 1
)
[2018-10-25 18:53:08] Processed: App\Jobs\BaseJob
延时任务
在某些情况下我们需要延时执行一些任务,delay
方法可以很好的协助我们完成这个操作。
这次我们先执行任务监听命令,去掉 --once
参数:
php artisan queue:work --queue=MyQueue
然后修改 queue
方法如下:
public function queue() {
var_dump(BaseJob::dispatch(['name' => 'Max Sky', 'gender' => 1])
->onQueue('MyQueue')
// 此处使用了 Laravel 内置的 Carbon 库,Carbon 是一个优秀的时间工具类
// Carbon::now() 表示获取当前时间;addSecond 表示在当前时间上增加 10 秒
// 意思就是延时 10s 后执行任务
->delay(Carbon::now()->addSecond(10)));
}
接着刷新网页,结果如下:
object(Illuminate\Foundation\Bus\PendingDispatch)[467]
protected 'job' =>
object(App\Jobs\BaseJob)[463]
public 'tries' => int 3
public 'timeout' => int 60
private 'type' => null
private 'data' =>
array (size=2)
'name' => string 'Max Sky' (length=7)
'gender' => int 1
protected 'job' => null
public 'connection' => null
public 'queue' => string 'MyQueue' (length=7)
public 'chainConnection' => null
public 'chainQueue' => null
public 'delay' =>
object(Carbon\Carbon)[469]
public 'date' => string '2018-10-25 19:05:32.647479' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'PRC' (length=3)
public 'chained' =>
array (size=0)
empty
赶紧回到命令行,等待 10s 后命令行有了结果【小误差请忽略。。。】:
[2018-10-25 19:05:34] Processing: App\Jobs\BaseJob
Array
(
[name] => Max Sky
[gender] => 1
)
[2018-10-25 19:05:34] Processed: App\Jobs\BaseJob
使用仪表盘
如果已安装 laravel/horizon
并发布了配置文件,我们可以利用仪表盘来管理任务。
编辑 config/horizon.php
,在最下方的 environments
中,将 production
和 local
内的 queue
分别加上我们的自定义队列名称。
结果如下:
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default', 'MyQueue'], // 此处添加队列名称
'balance' => 'auto',
'processes' => 10,
'tries' => 3,
],
],
'local' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default', 'MyQueue'], // 此处添加队列名称
'balance' => 'auto',
'processes' => 3,
'tries' => 3,
],
],
],
然后我们直接执行如下命令就可以监听队列任务,并通过仪表盘页面查看任务信息了:
【执行如下命令后,可替代之前的队列命令,意味着无需再执行 php artisan queue:work --MyQueue
】
php artisan horizon
成功后命令行返回 Horizon started successfully.
最后我们访问 http://localhost/horizon 就进入了仪表盘页面。
左边可以查看最近的任务、失败的任务等相关信息。
仪表盘默认只能在本地环境中使用,如需在发布环境中使用需配置自定义授权规则:Horizon - 仪表盘权限验证 |《Laravel 5.5 中文文档》 | PHP / Laravel 社区文档
更多
本文章对 Laravel 5.5 中的队列使用做了比较简单的描述,更多信息包括优先级、Supervisor 使用、失败任务处理、重试次数等参考文档翻译:队列 | 《Laravel 5.5 中文文档》 | PHP / Laravel 社区文档