Laravel 5.5 Redis 队列基本使用指南

版权声明:Max Sky 原创文章,转载时请保留所有权并以超链接形式标明文章出处。否则将追究相关法律责任。 https://blog.csdn.net/maxsky/article/details/83381853

仪表盘【适用于 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() 方法。

对于测试控制器,路由部分我是这么玩儿的

  1. app\Http\Controllers 下创建 TestController 控制器
  2. 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

Queue

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 中,将 productionlocal 内的 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 社区文档

猜你喜欢

转载自blog.csdn.net/maxsky/article/details/83381853