如何使用 Laravel 的队列机制?有哪些场景需要使用队列 ?

in Laravel with 0 comment

为什么 ?

首先,我们要知道为什么要使用队列,不使用队列会怎么样!优缺点如何

我们可以举例 几个简单场景。

邮件发送

邮件发送一般会面临哪些问题 ??

使用队列的好处在与哪里

通过此邮件发送,可能会导致多个耗时任务的产生,那我们其实也可以构建出多个 **队列服务** 出来。每个队列管理 自己的事情,很好的 **解耦** 他们

通过 Laravel 队列 可以很好的进行设置 **立即发送**、**延迟发送**、**重试发送**

其他

当然 我们还有很多种情况都会用到

如何使用 Laravel 队列

这里只是列出,大概的使用方向,和如何更好的去使用。代码可能跑不起起来,主要是理解 逻辑
我们这里 使用的是 Redis 作为驱动

驱动设置为 Redis

> .env
QUEUE_CONNECTION=redis
> 在 config/queue.php 中可以找到

快速创建队列 和 投递任务

# 创建 任务
php artisan make:job ProcessPodcast

自动生成 app/Jobs/EmailJob.php

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

    protected $data;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(array $data)
    {
        $this->data = $data;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $service = new EmailService();

        // ... 检查当前可用 Mailer
        // 这里你自定义就好了,这个方法中你可以根据你自己的配置,获取到当前可用的配置
        $mailer = $service->getMailer();

        // ... 获取当前要发送的数据
        $data = $this->data;
        
        $service->send($mailer, $data);
    }
}

一些常用操作

这些操作都能从 文档中找到

调用 发送

# 延迟 2分钟 发送
# 这里使用的是 Crontab 包 (不过 Laravel 自带)
EmailJob::dispatch()->delay(now()->addMinutes(2));

# 立即发送 (不会进入到队列中)
EmailJob::dispatchNow();

这里的队列默认用的 是 defult 队列,我们可以修改为指定队列服务

public function __construct(array $data)
{
    # 使用 emailQueue
    $this->onQueue('emailQueue');
    $this->data = $data;
}

设置失败情况下重试次数

# 重试 5 次
public $tries = 5;

设置超时时间

/**
* 确定任务应该超时的时间
*
* @return \DateTime
*/
public function retryUntil()
{
    return now()->addMinutes(10);
}

启动我们的队列

如果不配置 onQueue 的话,可以不带 ---queue 参数配置
php artisan queue:work --queue=emailQueue

结合 Events 来解耦

Laravel Event 也是通过 队列实现的
# 创建 Event
php artisan make:event FailEvent

class FailEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    protected $data;
    protected $tag;

    /**
     * @param array $data 投递的数据
     * @param string $tag 要操作的事情
     */
    public function __construct(array $data, string $tag = 'system')
    {
        $this->data = $data;
        $this->tag = $tag;
    }
}

# 创建 listener 
php artisan make:listener FailListener
class FailListener
{
    /**
    * Handle the event.
    * 
    * @param  object  $event
    * @return void
    */
    public function handle(FailEvent $event)
    {
        $this->{$event->tag}($event->data);
    }

    /**
     * 处理系统异常
     * DateTime: 2021/12/3 11:02 上午
     * @param array $data
     */
    public function system(array $data)
    {

    }

    /**
    * 处理邮件异常
    * DateTime: 2021/12/3 11:02 上午
    */
    public function email()
    {
    
    }

}

# app/Providers/EventServiceProvider.php
protected $listen = [
    FailEvent::class => [
        FailListener::class,
    ],
]

# 投递
event(new FailEvent(['error' = '异常信息'], 'email'));

其他

其实,Laravel 大多数帮我实现了整个流程而已。可以尝试自己使用 redis 来实现一个可控队列。熟练是掌握 Redis 相关数据类型即可.
这里简要列出 Redis 中,在以上模式中会用到的数据类型

当然,Redis 的用法还有很多,满足自己的需求即可。

世界上没有完美的解决方案,只有最适合你自己的方案,在工作中遇到问题,尽量要学会举一反三,合理的运用各种 工具,设计方案去实现。
代码 只是最终一个缩影而已,最终的要学会理解,每个语言 每个框架,也只是一种方案的实现,融会贯通才无敌 ...

参考文章

Laravel 队列文档

Comments are closed.