Laravel 队列(Queue)是处理耗时任务的强大工具,比如邮件发送、图片处理、API 请求、定时任务等。如果你还在同步执行这些操作,导致用户等待时间长,那一定要学会 Laravel 队列。
本文会手把手带你入门 Laravel 队列,包括基本概念、驱动配置、任务创建、队列监听、错误处理,让你从 0 到 1 熟练使用 Laravel 队列。
1. 为什么要用 Laravel 队列?
假设你的应用有以下需求:
✅ 用户注册时发送邮件 (同步发送会卡住页面)
✅ 订单支付后通知供应商 (外部 API 请求慢)
✅ 用户上传图片后生成缩略图 (图片处理很耗时)
✅ 定期清理数据库、发送定时通知(后台任务)
如果你把这些任务同步执行 ,用户必须等所有操作完成,体验会很差。
解决方案 :使用 Laravel 队列,让这些任务异步执行,不阻塞主线程,提高应用响应速度!
2. Laravel 队列基本概念
Laravel 队列的核心流程:
1️⃣ 创建 Job(任务) :定义具体要执行的代码逻辑
2️⃣ 分发 Job 到队列 :使用 dispatch()
把任务推到队列中
3️⃣ 队列驱动 :存储队列任务的数据(Redis、Database等)
4️⃣ 队列监听器:从队列取出任务,执行并删除
3. 配置 Laravel 队列
Laravel 默认使用 sync
(同步执行),需要手动改成队列模式。
3.1 选择队列驱动
Laravel 目前支持的队列驱动:
✅ database
------ 使用 MySQL 存储任务(适合小项目)
✅ redis
------ 高性能,推荐生产环境使用
✅ beanstalkd
------ 高效消息队列(需要额外安装)
✅ sqs
------ Amazon SQS
3.2 配置 .env
ini
ini
复制编辑
QUEUE_CONNECTION=redis # 使用 Redis 作为队列驱动
然后在 config/queue.php
里修改:
bash
php
复制编辑
'default' => env('QUEUE_CONNECTION', 'redis'),
📌 推荐使用 Redis,因为它性能好,支持延迟队列和失败任务重试。
4. 创建 Laravel 队列任务(Job)
Laravel 提供了 make:job
命令来创建任务:
go
bash
复制编辑
php artisan make:job SendEmailJob
在 app/Jobs/SendEmailJob.php
里,Laravel 自动生成了 handle()
方法,我们在这里编写具体任务逻辑。
php
php
复制编辑
namespace App\Jobs;
use Mail;
use App\Models\User;
use App\Mail\WelcomeEmail;
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;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
// 任务构造函数,接收参数
public function __construct(User $user)
{
$this->user = $user;
}
// 任务执行逻辑
public function handle()
{
Mail::to($this->user->email)->send(new WelcomeEmail($this->user));
}
}
📌 这个任务会给用户发送邮件,但不会同步执行,而是加入队列,后台运行。
5. 任务推送到队列
在控制器里,我们可以用 dispatch()
把任务加入队列:
ini
php
复制编辑
use App\Jobs\SendEmailJob;
use App\Models\User;
$user = User::find(1);
dispatch(new SendEmailJob($user));
或者使用 延迟执行
scss
php
复制编辑
dispatch(new SendEmailJob($user))->delay(now()->addMinutes(5));
📌 任务不会立即执行,而是进入 Redis / Database 队列,后台执行!
6. 启动 Laravel 队列监听器
队列任务进入队列后,需要有个"工人"来执行它们。Laravel 提供了 queue:work
命令来监听队列:
arduino
bash
复制编辑
php artisan queue:work
这个命令会不断监听队列,一旦有新任务,就会立即执行。
6.1 让队列一直运行
Laravel 队列默认执行一次后就退出,为了让它持续运行,我们可以用 --daemon
选项:
arduino
bash
复制编辑
php artisan queue:work --daemon
但这个方法不够稳妥,推荐使用 Supervisor 来守护进程。
6.2 生产环境用 Supervisor 监听队列
在 Ubuntu 服务器上安装 Supervisor:
bash
复制编辑
sudo apt install supervisor
然后创建 queue-worker.conf
:
ini
ini
复制编辑
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work --tries=3
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/laravel-worker.log
启动 Supervisor:
sql
bash
复制编辑
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
📌 这样就可以让 Laravel 队列进程一直运行,即使服务器重启也不会中断!
7. 处理失败任务
如果任务执行失败,Laravel 会自动重试 3 次(默认值,可在 queue:work --tries=5
设置)。
如果任务还是失败,可以用以下命令检查失败队列:
arduino
bash
复制编辑
php artisan queue:failed
然后重新执行失败任务:
arduino
bash
复制编辑
php artisan queue:retry all
或者删除失败任务:
arduino
bash
复制编辑
php artisan queue:flush
📌 生产环境下,一定要用 Redis 作为队列,并配置 Supervisor 监控,防止任务丢失!
8. 进阶用法
8.1 指定队列名称
可以在 dispatch()
时指定任务进入特定队列:
scss
php
复制编辑
dispatch(new SendEmailJob($user))->onQueue('emails');
然后启动监听指定队列:
arduino
bash
复制编辑
php artisan queue:work --queue=emails
8.2 任务唯一性
有些任务不希望重复执行,比如避免重复发送邮件:
kotlin
php
复制编辑
class SendEmailJob implements ShouldQueue, ShouldBeUnique
这样即使多次 dispatch 这个任务,Laravel 也会只执行一次。
总结
步骤 | 操作 |
---|---|
1. 选择队列驱动 | 配置 .env 选择 database 或 redis |
2. 创建任务 | php artisan make:job TaskName |
3. 推送任务 | dispatch(new TaskName($param)) |
4. 监听队列 | php artisan queue:work |
5. 失败任务管理 | queue:failed , queue:retry |
6. 生产环境优化 | 用 Redis + Supervisor 守护进程 |
Laravel 队列让异步任务变得简单易用,提高性能的同时还能减少页面等待时间。你可以用它来优化邮件发送、数据处理、定时任务等各种耗时操作。
现在,你可以尝试在项目里加上 Laravel 队列,看看是否能提升响应速度!赶紧去试试吧!