Laravel 8 笔记:队列Queue的使用及扩展知识

具体以redis驱动为例,来介绍如何使用laravel队列,包括一些laravel队列相关的扩展知识,比如多队列的使用,queue:workqueue:listen的区别等。

laravel queue 队列使用

示例在laravel 8.24 + php 7.4环境运行。

配置连接和队列

.env里配置好redis配置参数,以及QUEUE_CONNECTION的配置。

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=
REDIS_PORT=6379

QUEUE_CONNECTION=redis

查看config/database.php里的连接配置redis配置。

'redis' => [
    ...

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

    ...

]

配置config/queue.php,这里面是redis连接指定队列default,具体参数参考文章官方文档(文章底部)。

'connections' => [
    ...
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => 'default',
        'retry_after' => 90,
        'block_for' => null,
    ],
    ...

],

以上这些配置基本就是laravel的默认配置。

任务模型

新建一个任务SendMail

artisan make:job SendMail

会在app/Jobs下生成SendMail任务,我们来写一个假逻辑,从构造函数中获取运行需要的参数,在handle()中处理任务逻辑:

<?php

namespace AppJobs;

use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;

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

    private data;

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

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // 处理一些逻辑
        doSomething(this->data); 
    }
}

分发任务

在业务代码中向队列分发任务:

// 向默认队列分发任务
SendMail::dispatch(data);

// 指定队列
SendMail::dispatch(data)->onQueue('high');

// 延迟分发
SendMail::dispatch(data)->delay(Carbon::now()->addMinutes(15));

// 同步调度,将会直接在当前进程中执行这个任务
SendMail::dispatchSync(data);

处理任务

直接运行命令即可处理队列里的任务。

php artisan queue:work

生产环境需要使用supervisor守护队列执行进程,根据需要增加进程数量。

常用运行配置项

指定队列执行优先级,每次查看有无新任务之间的间隔时间等配置项。

// 处理redis连接里  的 high 和 default 队列,high 优先级更高
php artisan queue:work redis --queue=high,default

// 新任务间隔事件
php artisan queue:work --sleep=3

// 失败重试次数3,失败后延迟执行时间5
php artisan queue:work redis --tries=3 --backoff=5

全部运行配置项

--name[=NAME]          The name of the worker [default: "default"]
--queue[=QUEUE]        The names of the queues to work
--daemon               Run the worker in daemon mode (Deprecated)
--once                 Only process the next job on the queue
--stop-when-empty      Stop when the queue is empty
--delay[=DELAY]        The number of seconds to delay failed jobs (Deprecated) [default: "0"]
--backoff[=BACKOFF]    The number of seconds to wait before retrying a job that encountered an uncaught exception [default: "0"]
--max-jobs[=MAX-JOBS]  The number of jobs to process before stopping [default: "0"]
--max-time[=MAX-TIME]  The maximum number of seconds the worker should run [default: "0"]
--force                Force the worker to run even in maintenance mode
--memory[=MEMORY]      The memory limit in megabytes [default: "128"]
--sleep[=SLEEP]        Number of seconds to sleep when no job is available [default: "3"]
--timeout[=TIMEOUT]    The number of seconds a child process can run [default: "60"]
--tries[=TRIES]        Number of times to attempt a job before logging it failed [default: "1"]

失败任务处理

为了记录失败任务,需要一个数据表,运行:

php artisan queue:failed-table

php artisan migrate

在处理任务时,指定在遇到执行失败的重试次数

php artisan queue:work --tries=3

在任务文件中可以做更多的处理:

/**
* 计算在重试任务之前需等待的秒数,第一次重试延迟1s,第二次5s,第三次10s
*
* @return array
*/
public function backoff()
{
    return [1, 5, 10];
}

 /**
 * 任务处理失败
 *
 * @param  Throwable  exception
 * @return void
 */
 public function failed(Throwableexception)
 {
 // 给用户发送失败通知, 等等...
 }

任务重试命令

查看失败任务,也就是数据表“failed_jobs中的内容。

php artisan queue:failed

重试和删除失败任务

// 重试全部失败任务
php artisan queue:retry all

// 指定ID重试
php artisan queue:retry 5

// 删除一个失败任务
php artisan queue:forget 5

// 清理全部失败任务
php artisan queue:flush

扩展

多队列使用

经过测试,laravel默认有一个default队列,如果要使用多队列,直接在分发任务时指定队列就可以了,并不需要特殊配置,关于多队列时执行的优先级问题,看上面的处理任务常用配置项。

使用queue:work和queue:listen处理任务有什么不一样

官方更推荐使用queue:work来处理任务,说明是它比queue:listen的效率更高。

  • queue:work使用的是已经缓存的代码当然效率更高,这使它的效率更高,但是同时queue:work需要重启才能应用新的代码去处理任务,所以每次更新代码之后,需要重启queue:work进程使新代码生效。
  • queue:listen使用不存在缓存的问题,更新代码不用重启,但是效率会低一丢丢。
  • 他们的执行选项几乎一样

综上,生产环境用queue:work,而开发环境由于代码变动频繁,性能影响也不大推荐使用queue:listen

更多扩展

参考文档

  • https://learnku.com/docs/laravel/8.x/queues/9398#connections-vs-queues

  • https://laracasts.com/discuss/channels/laravel/multiple-queues-for-redis-connection

  • https://stackoverflow.com/questions/41991251/what-is-the-difference-queuework-and-queuelisten/41991848
Laravel 8 笔记:队列Queue的使用及扩展知识

原文链接:https://beltxman.com/3505.html,若无特殊说明本站内容为 行星带 原创,未经同意禁止转载。

发表评论

您的电子邮箱地址不会被公开。

Scroll to top