欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > laravel中队列使用

laravel中队列使用

2024/11/30 8:56:56 来源:https://blog.csdn.net/caidingnu/article/details/144056253  浏览:    关键词: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,代码如下:

<?phpnamespace 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!']);
}

注意事项

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com