Laravel Queue—消息队列任务

Laravel Queue—消息队列任务

laravel队列的使用

队列可以通过多种方式实现,在config/queue.php配置connection

//这里配置了三种方式,具体选哪一种,需要在.env配置 QUEUE_CONNECTION=redis
'connections' => [
        'sync' => [
            'driver' => 'sync',
        ],
        'database' => [
            'driver' => 'database',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 90,
        ],
        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 90,
            'block_for' => null,
        ],
    ],

这里以redis为例子。

1.安装Predis扩展包

$ composer require predis/predis

2.在.env配置redis连接配置

3.创建任务类,实现的时候就是把任务实例放入到队列中,消费的时候就是执行任务实例的handle方法

php artisan make:job SendEmail

会创建类文件app/jobs/SendEmail.php

其他重要属性:

public $tries = 5; //表示 任务最大尝试次数
public $timeout = 120; //单个任务运行超时时间
 public function __construct(User $user)
    {
        $this->user = $user;
    }
 public function handle()
    {
        sleep(2);
        echo '任务执行'.$this->user->name;
    }

4.任务分发dispatch(就是写入队列)

delay就是延迟分发( 我们指定一个任务在分配后 10分钟内不可被处理 )

onQueue(‘sendEmail’),就在指定队列,如果没有指定,都会放到默认的队列中。

onConnection('redis2),就是指定redis服务连接。

public function add()
    {
        $user = new User();
        $user->name = 'aabc';
        $user->email = '[email protected]';
        $user->password = '[email protected]';
        $user->save();
        //向job添加一个任务
        \App\Jobs\SendEmail::dispatch($user)->delay(now()->addMinutes(1))-      >onQueue('sendEmail');
        echo '用户添加成功\n';
    }

5.消费队列,会启动一个常驻进程来消费,我们也可以用命令来消费​

php artisan queue:work  //这个命令会执行所有的队列
php artisan queue:work redis2 //执行指定这个连接的队列
php artisan queue:work redis2 --queue=emails //执行指定队列

执行每个任务队列,系统都是常驻进程模式运行,所以在handle中要释放资源型变量。修改了代码后,也要注意重启消费进程

php artisan queue:restart

laravel队列实现原理

队列服务注册

protected function registerManager()
{
    $this->app->singleton('queue', function ($app) {
        return tap(new QueueManager($app), function ($manager) {
            $this->registerConnectors($manager);
        });
    });
}

可以看出,队列的门面操作的是Illuminate\Queue\QueueManager类

重要属性protected $connections = [];protected $connectors = [];

$connectors,该成员变量中存储着所有 laravel 支持的底层队列服务:'Database', 'Redis', 'Beanstalkd', 'Sqs'。 保存一个闭包,这个闭包就是返回 redisConnectorSqsConnectorDatabaseConnectorBeanstalkdConnector 各种连接器,例如redisConnector

Illuminate\Queue\Connectors\RedisConnector


class QueueManager implements FactoryContract, MonitorContract
{
    public function addConnector($driver, Closure $resolver)
    {
        $this->connectors[$driver] = $resolver;
    }
}

$connections = []就是保存各种连接器执行connect方法返回的对象,比如

Illuminate\Queue\RedisQueue
protected function resolve($name) //这个方法就是返回Illuminate\Queue\RedisQueue
    {
        $config = $this->getConfig($name);
​
        return $this->getConnector($config['driver']) 
                        ->connect($config)
                        ->setConnectionName($name);
    }

所以我们操作的很多方法其实都是使用Illuminate\Queue\RedisQueue类的方法,这就是实现队列的工具。

class RedisQueue extends Queue implements QueueContract
{
    public function push($job, $data = '', $queue = null)
    {
        return $this->pushRaw($this->createPayload($job, $data), $queue);
    }
​
    public function pushOn($queue, $job, $data = '')
    {
        return $this->push($job, $data, $queue);
    }
​
    public function later($delay, $job, $data = '', $queue = null)
    {
        return $this->laterRaw($delay, $this->createPayload($job, $data), $queue);
    }
​
    public function laterOn($queue, $delay, $job, $data = '')
    {
        return $this->later($delay, $job, $data, $queue);
    }
}

猜你喜欢

转载自blog.csdn.net/littlexiaoshuishui/article/details/103953355