笔记:任务队列的简单使用

写在前面

Laravel 队列系统是通过将耗时的任务(如发送邮件、处理大型文件等)放入队列中,然后由后台进程异步执行这些任务,从而提高性能和响应速度。
框架支持多种队列驱动,包括数据库、Redis、Amazon SQS、Beanstalkd 等。

快速开始

这里仅对 队列任务 做简单的快速入门使用,更多了解与使用请阅读官方文档!
参考文档:队列《Laravel 9 中文文档》

队列工作

队列是一个后台进程,负责监听队列并处理队列中的任务/Job。当有新任务被推送到队列时,队列会自动取出并执行相应的任务逻辑。
通常需要会配合 Supervisor 来确保队列任务进程一直处于存活状态!
启动队列:

php artisan queue:work --daemon

队列连接

Laravel 支持多种队列驱动,包括数据库、Redis、Amazon SQS、Beanstalkd 等。在配置文件 config/queue.php 中配置。
通常选择 Redisdatabase,一般情况下,我们选择 Redis 队列驱动。

QUEUE_CONNECTION=redis

配置失败的队列 job 表:failed_jobs

# failed_jobs
  php artisan queue:failed-table
  php artisan migrate

如果选择 database 驱动,则需要创建任务表:jobs

# 创建表 jobs
  php artisan queue:table
  php artisan migrate

队列任务

创建一个队列任务 Job 命令:

 php artisan make:job SendMsg

此命令会在 app/Jobs/ 路径下生成任务类 SendMsg.php ,任务类有一个 handle 方法,用来处理任务业务逻辑。

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Throwable;

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

    private string $phone;

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


    /**
     * 获取一个可以被传递通过的中间件任务
     *
     * @return array
     */
    public function middleware(): array
    {
        return [
            new RateLimited(), 
            new WithoutOverlapping()
        ];
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
        Log::info('SendMsg Job Started');
        sleep(10);
        Log::info('SendMsg Job finished');

    }

    /**
     * 任务失败时的处理逻辑
     *      如:发送通知
     * @param Throwable $exception
     * @return void
     */
    public function failed(Throwable $exception)
    {
        Log::info('SendMsg Job Failed');
    }

}

调度任务

任务使用 dispatch() 函数来分发一个队列任务。传递给 dispatch() 的参数将被传递给任务的构造函数,调度过程中可指定连接,队列,延迟调度等等。
参考:队列《Laravel 9 中文文档》
需要注意:

  1. 确保任务实际上能够执行成功;
  2. 任务类本身的 dispatch() 来调度,传递给 dispatch() 的参数(动态参数)将被传递给任务的构造函数,任务类注意接收;
  3. 特别说一个配置参数 ‘after_commit’ => false, 一般不要在配置文件修改!如果确实需要在所有数据库事务提交后才调度任务,可以使用 afterCommit() 方法;
  4. 任务链 chain() 方法,任务依赖于其他 多个顺序运行的任务 时,一个任务失败则其他任务都不会执行;
    1. 使用任务类的 ::withChain([new x1(), new x2()]) 方法
    2. 或者 Illuminate\Support\Facades\Bus::chain([]) 方法

参考代码:

    public function test(Request $request)
    {
        $phone = '13011223344';
        // 调度任务
        SendMsg::dispatch($phone)->afterCommit();

        //SendMsg::withChain([])->dispatch();
        //Bus::chain([])->dispatch();

    }

队列中间件

Laravel 任务中间件允许你围绕排队任务的执行封装自定义逻辑,从而减少了任务本身的代码。一般基本不会使用,但
参考代码:

<?php

namespace App\Jobs\Middleware;

use Illuminate\Support\Facades\Redis;

class RateLimited
{
    /**
     * 处理队列任务
     *
     * @param  mixed  $job
     * @param  callable  $next
     * @return mixed
     */
    public function handle($job, $next)
    {
        Redis::throttle('key')
                ->block(0)->allow(1)->every(5)
                ->then(function () use ($job, $next) {
                    // 获得了锁

                    $next($job);
                }, function () use ($job) {
                    // 没有获取到锁

                    $job->release(5);
                });
    }
}

其他

核心源码参考:Illuminate\Foundation\Bus\DispatchableIlluminate\Bus\Queueable;

Laravel 队列任务 不仅仅是异步任务逻辑实现,更是一种解决方案。在日常使用中,除了 发送邮件处理大型文件异步 场景外,更多的是配合 事件系统 的使用,这使得程序更加便捷健壮,也更加容易管理!

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!