Laravel-Job-Queue 任务队列机制

◇◆丶佛笑我妖孽 提交于 2020-03-18 11:25:40

某厂面试归来,发现自己落伍了!>>>

Job-Queue 任务-队列的应用场景,是将耗时的任务延时(异步)处理,比如发送邮件,从而大幅度缩短 Web 请求和响应的时间。

1,队列

1.1 连接和队列 connection 和 queue

在配置文件 config/queue.php 有一个 connections 配置项。该配置项定义了后台队列服务的特定 连接器,如 Amazon SQS, Beanstalk, 或 Redis。

每种队列连接器(connection)都可以有很多队列(queue),可以想象在银行办理不同业务的各个窗口队列。

<?php

return [
    //默认的队列连接名称
    'default' => env('QUEUE_CONNECTION', 'sync'),

    //队列连接名称
    'connections' => [
        'sync' => [
            'driver' => 'sync',
        ],
    .
    .
    .
        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 90,
            'block_for' => null,
        ],

    ],
    //失败队列连接器
    'failed' => [
        'database' => env('DB_CONNECTION', 'mysql'),
        'table' => 'failed_jobs',
    ],
];

请注意 queue 配置文件中的connections里面的每个连接器配置示例都有一个 queue 属性。比如上文中的redis,它的queue的默认值就是 default。当新的队列任务被添加到指定的连接时,该配置项的值就是默认监听的队列。换句话说,如果你没有指派特别的队列名称,那么 queue 的值,也是该任务默认添加到的队列。

1.2 使用Redis队列连接器

如果要使用 Redis 作为 队列连接器,则我们需要配置以下文件:

1.2.1 添加 Redis 包

在 composer.json 中 require 部分加入 "predis/predis": "~1.0",,然后 composer update 更新一下即可。

1.2.2 queue.php

首先需要去 .env 中配置 QUEUE_CONNECTION ,因为现在打算用 Redis,所以配置成 redis。

QUEUE_CONNECTION = redis

接着配置 queue.php 里 connections 部分 找到 redis 连接,

'redis' => [
      'driver' => 'redis',
      'connection' => 'default',
      'queue' => env('REDIS_QUEUE', 'default'),
      'retry_after' => 90,
      'block_for' => null,
],

这里的driver 是 redis,那我们要去找 redis 的配置文件。注意,这个redis 里面的connection 是 redis自己的子连接,不要和 queue 的 connection 混淆。

这里看到 redis 的子连接是 default,在database.php 中, 我们看到 redis 有三个子连接,其中就有 default。其中 connection 对应的值 default 就是 database.php 中 redis 的那个 default 连接。也就是说,queue.php中['connections']['redis']['connection'] 的 default,指向的就是 database.php中 ['redis']['default'] 下面的值。也可以按照自己的需求进行修改。

1.2.3 database.php

根据这个默认连接中需要的配置项,编辑 .env 配置文件,将其中的 REDIS_HOST、REDIS_PASSWORD、REDIS_PORT 填写成自己服务器中 Redis 的相应值。

<?php

return [

    'default' => env('DB_CONNECTION', 'mysql'),
.
.
.
    'redis' => [

        'client' => 'predis',

        'default' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

    ],

];

2,任务类

接下来就是写实际的操作类了,Laravel 提供了 artisan 命令简化创建任务类:

php artisan make:job Test

在 app/Jobs目录下,生成一个Test.php 任务类。

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class Test implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //业务逻辑处理
        logger()->channel('abc')->info('test 456 at:'.date('Y-m-d H:i:s', time()));
    }
}

我们直接在handle方法中,做相应的业务逻辑处理。

3,发放任务

现在写个入口函数,推送任务到队列中。使用辅助函数 dispatch():

<?php

use App\Jobs\Test as TestJob;

class AbcController extends Controller
{
    public function test()
    {   
        dispatch(new Test('I am dispatching test job with 123'));
        var_dump('123 at'.date('Y-m-d H:i:s', time()));
        exit();
    }
}

开启队列

顺利的话,这是最后一步了。命令行中执行:

php artisan queue:work {connectionName} {--queue=queueName}

这里的 connectionName 就是 queue.php 文件中的 connections里面的字符串键,如 sync, database, sqs, redis 等,如果不带这个参数,则会使用 queue.php 里 default 键指向的 连接名。

当然 connections里面也可以自己添加connection,比如 

'abc' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 90,
            'block_for' => null,
        ],

--queue=queueName 这个是指明某个队列,把特定的队列起起来。我们看到 除了 sync 外,其他的连接的设置里,都有 queue 这个配置。如果这里不加这个参数,则会把配置的那个队列起起来,默认值是 default。

 

注意:在把队列起起来之前,要确保 之前的其他机制是否有向这个队列中扔过任务,是否还有未处理完的任务。如果有,且不需要再执行了,我们可以通过 php artisan cache:clear 这个命令,把那些任务从队列中清除。但一定要确认这些任务是无用的,不需要再执行的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!