当前位置: 首页 > article >正文

laravel中队列使用

Laravel 提供了强大的队列系统,允许开发者将耗时任务推送到后台执行,从而提升系统性能和用户体验。本文将从基本使用到深入解析,结合单进程队列的特点,完整地介绍 Laravel 队列的使用。

队列的作用和场景*

在 Web 开发中,一些任务会占用较长时间,例如:

​ • 发送邮件:用户注册成功后需要发送欢迎邮件。

​ • 生成报表:复杂报表需要长时间计算和数据处理。

​ • 推送通知:需要通过第三方服务发送推送。

将这些任务放在 HTTP 请求中会导致用户等待时间过长,影响体验。Laravel 的队列系统将这些任务推到后台运行,前端只需快速响应即可。

队列的安装与配置**

1. 配置队列驱动

Laravel 支持多种队列驱动,如 database、Redis、beanstalkd 等。默认驱动为 sync,即同步执行任务。修改 .env 文件以指定驱动:

QUEUE_CONNECTION=redis

安装与配置 Redis

2. 安装 PHP Redis 扩展

通过 Composer 安装 PHP 的 Redis 扩展:

composer require predis/predis

或者安装官方扩展:

# Ubuntu
sudo apt install php-redis

# CentOS
sudo yum install php-redis

Laravel 配置 Redis 队列

1. 修改队列连接设置

在 .env 文件中将队列驱动改为 redis:

QUEUE_CONNECTION=redis

2. 配置 Redis 连接

Laravel 默认使用 config/database.php 中的 Redis 配置,无需额外改动。默认配置如下:

'redis' => [
    'client' => 'phpredis', // 或 '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),
    ],
    'queue' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => env('REDIS_QUEUE_DB', 1), // 队列可以使用独立的 Redis 数据库
    ],
],

确保 .env 中的 Redis 配置正确:

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_DB=0
REDIS_QUEUE_DB=1

运行 Redis 队列

. 启动队列进程

单进程运行解析

php artisan queue:work redis  --queue=emails --tries=3 --timeout=60

​ • redis:指定使用 Redis 作为队列驱动。

​ • --tries=3:失败重试次数。默认:无限次

​ • --timeout=60:任务最大执行时间。任务执行时间超过 60 秒会超时,标记为失败

  • –queue 指定队列名称 (例如,任务被分配到不同队列(emails, notifications),可以选择只处理 emails 队列的任务。)

  • –memory 限制队列进程的内存使用(单位:MB)

  • –sleep 设置没有任务时,进程的等待时间(单位:秒)(php artisan queue:work redis --sleep=3 如果队列为空,进程会等待 3 秒再尝试获取新任务。)

任务会按照队列的先进先出顺序(FIFO)串行执行。假设队列中有任务 A、B、C:

​ 1. 任务 A 被处理完成后,任务 B 才会开始。

​ 2. 任务 B 完成后,任务 C 开始。

​ 3. 当前任务完成后,工作进程会继续监听队列中新的任务。

这种运行方式仍然是异步的,任务不会阻塞 HTTP 请求响应,而是后台依次执行。

多进程运行

php artisan queue:work --tries=3 --timeout=60 &
php artisan queue:work --tries=3 --timeout=60 &
php artisan queue:work --tries=3 --timeout=60 &
php artisan queue:work --tries=3 --timeout=60 &
如果需要给队列取名

–queue=emails

php artisan queue:work redis --queue=emails1 --tries=3 --timeout=60 &
php artisan queue:work redis --queue=emails2 --tries=3 --timeout=60 &
php artisan queue:work redis --queue=emails3 --tries=3 --timeout=60 &
php artisan queue:work redis --queue=emails4 --tries=3 --timeout=60 &
php artisan queue:work redis --queue=emails5 --tries=3 --timeout=60 &

如果启动多个队列工作进程,队列中的任务将被多个进程同时处理。例如:

​ • 任务 A 分配给第一个进程。

​ • 任务 B 分配给第二个进程。

​ • 如果有更多任务,它们会被动态分配给空闲进程。

这种方式提高了队列处理的并发能力,适合需要高吞吐量的场景。

优化与最佳实践**

1. 使用 Supervisor 管理队列

在生产环境中,使用 Supervisor 可以确保队列进程始终运行。

配置 Supervisor

在 /etc/supervisor/conf.d/laravel-worker.conf 中添加以下内容:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/project/artisan queue:work --tries=3 --timeout=60
autostart=true
autorestart=true
numprocs=4
redirect_stderr=true
stdout_logfile=/path/to/project/worker.log

启动 Supervisor:

# 重新加载 Supervisor 配置
sudo supervisorctl reread

# 更新 Supervisor 进程
sudo supervisorctl update

# 启动所有 laravel-worker 进程
sudo supervisorctl start laravel-worker:*

numprocs: 启动4个队列进程

2 验证运行状态

运行以下命令查看进程状态:

sudo supervisorctl status

输出示例:

laravel-worker:laravel-worker_00   RUNNING   pid 1234, uptime 0:01:00
laravel-worker:laravel-worker_01   RUNNING   pid 1235, uptime 0:01:00
laravel-worker:laravel-worker_02   RUNNING   pid 1236, uptime 0:01:00
laravel-worker:laravel-worker_03   RUNNING   pid 1237, uptime 0:01:00

3. 多队列分配

如果需要针对不同的队列启动多个进程,例如分别处理 emails 队列和 notifications 队列,可以配置多个程序块。

[program:emails-queue]
command=php /path/to/project/artisan queue:work redis --queue=emails --tries=3 --timeout=60
autostart=true
autorestart=true
numprocs=2
redirect_stderr=true
stdout_logfile=/path/to/project/logs/emails_queue.log

[program:notifications-queue]
command=php /path/to/project/artisan queue:work redis --queue=notifications --tries=3 --timeout=60
autostart=true
autorestart=true
numprocs=2
redirect_stderr=true
stdout_logfile=/path/to/project/logs/notifications_queue.log

[program:reports-queue]
command=php /path/to/project/artisan queue:work redis --queue=reports --tries=3 --timeout=60
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/path/to/project/logs/reports_queue.log

此配置会分别启动两个队列,每个队列都有两个工作进程。

使用

创建与调度任务

php artisan make:job SendEmailJob

生成的类位于 app/Jobs/SendEmailJob.php,代码如下:

<?php

namespace App\Jobs;

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

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

    protected $email;

    public function __construct($email)
    {
        $this->email = $email;
    }

    public function handle()
    {
        // 模拟邮件发送逻辑
        \Mail::to($this->email)->send(new \App\Mail\WelcomeMail());
    }
}

提交任务

控制器中提交

use App\Jobs\SendEmailJob;

public function sendEmail(Request $request)
{
    $email = $request->input('email');
    
    // 将任务加入队列,不指定队列
    SendEmailJob::dispatch($email);
 // --------------------------- 指定队列 
  // 第一个任务
SendEmailJob::dispatch($email)->onQueue('emails');

// 第二个任务
 SendNotificationJob::dispatch($email)->onQueue('notifications');

    return response()->json(['message' => 'Email is being sent!']);
}

注意事项

任务可能会因为失败被多次执行,因此任务逻辑需要设计为幂等。例如,为每个任务分配唯一标识,避免重复处理。


http://www.kler.cn/a/411859.html

相关文章:

  • 【通俗理解】神经网络中步长缩小的奥秘:优化算法与卷积操作的影响
  • 设计模式——MVC模式
  • 自动化的内存管理技术之垃圾回收机制-JavaScript引用数据内存回收机制
  • EXTI配置流程 含中断延时消抖点亮小灯
  • Matlab 深度学习 PINN测试与学习
  • 嵌入式的C/C++:深入理解 static、const 与 volatile 的用法与特点
  • 基于FPGA的信号DM编解码实现,包含testbench和matlab对比仿真
  • linux运行vue编译后的项目
  • ensp静态路由实验
  • CTF-RE 从0到N:c语言是如何利用逻辑运算符拆分变量和合并的
  • LeetCode数组题
  • C# Http Post 长连接和短连接请求
  • 【jvm】对象的内存布局
  • 【软件入门】Git快速入门
  • 《黑神话:悟空》游戏辅助修改器工具下载指南与操作方法详解
  • 4.6 JMeter HTTP信息头管理器
  • git(Linux)
  • C++:多态的原理
  • VMware ubuntu创建共享文件夹与Windows互传文件
  • Unity中的简易TCP服务器/客户端
  • macos 14.0 Monoma 修改顶部菜单栏颜色
  • Leetcode53. 最大子数组和(HOT100)
  • numpy.digitize函数介绍
  • 缺失的第一个正数(java)
  • 挂载本地目录到k8s的pod实现持久化存储
  • [java] 什么是 Apache Felix