本文将介绍如何在 Laravel 中使用队列,以及了解了为什么使用队列
什么情况使用队列?
耗时的,比如上传一个文件后进行一些格式的转化等。
需要保证送达率的,比如发送短信,因为要调用别人的 api,总会有几率失败,那么为了保证送达,重试就必不可少了。
记录使用过程:
一、配置队列存储
队列配置文件存放在 config/queue.php,默认为 sync 同步处理,这里可以选择 redis,database 等,使用方法如下。
数据库
创建数据表存储任务,执行完 artisan 命令后运行数据迁移
- php artisan queue:table
- php artisan migrate
复制代码
Redis
为了使用 redis 队列驱动,你需要在你的配置文件 config/database.php 中配置Redis的数据库连接。
如果你的 Redis 队列连接使用的是 Redis 集群,你的队列名称必须包含 key hash tag。这是为了确保所有的 Redis 键对于一个给定的队列都置于同一哈希中:- 'redis' => [
- 'driver' => 'redis',
- 'connection' => 'default',
- 'queue' => 'default',
- 'retry_after' => 90,
- ],
复制代码
二、创建任务类
队列的任务类在 app/Jobs/ 目录下
php artisan make:job SaveBusLine
修改文件如下:- namespace App\Jobs;
- use App\Http\Repository\BusRepository;
- use Illuminate\Bus\Queueable;
- use Illuminate\Queue\SerializesModels;
- use Illuminate\Queue\InteractsWithQueue;
- use Illuminate\Contracts\Queue\ShouldQueue;
- use Illuminate\Foundation\Bus\Dispatchable;
- class SaveBusLine implements ShouldQueue
- {
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- /**
- * 任务最大尝试次数。
- *
- * @var int
- */
- public $tries = 3;
- /**
- * 任务运行的超时时间。
- *
- * @var int
- */
- public $timeout = 60;
- private $datum;
- /**
- * Create a new job instance.
- * @param array|object $datum
- *
- * @return void
- */
- public function __construct($datum)
- {
- $this->datum = $datum;
- }
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- BusRepository::getInstent()->updateBusLine($this->datum);
- }
- }
复制代码
在控制器或仓库中调用队列方法:- use App\Jobs\SaveBusLine;
- use Carbon\Carbon;
- /***************** 队列操作 start *******************/
- SaveBusLine::dispatch($arrayData)->delay(Carbon::now()->addMinute(1));
- /***************** 队列操作 end *******************/
复制代码
三、启动队列任务
php artisan queue:work
四、Supervisor 配置
安装 Supervisor
Supervisor 是一个 Linux 操作系统上的进程监控软件,它会在 queue:listen 或 queue:work 命令发生失败后自动重启它们。在 Ubuntu 安装 Supervisor,可以用以下命令:- sudo apt-get install supervisor
复制代码
{tip} 如果自己手动配置 Supervisor 听起来有点难以应付,可以考虑使用 Laravel Forge,它能给你的 Laravel 项目自动安装与配置 Supervisor。
配置 Supervisor
Supervisor 的配置文件一般是放在 /etc/supervisor/conf.d 目录下。在这个目录中你可以创建任意数量的配置文件来要求 Supervisor 怎样监控你的进程。例如我们创建一个 laravel-worker.conf 来启动与监控一个 queue:work 进程:- [program:laravel-worker]
- process_name=%(program_name)s_%(process_num)02d
- command=php ~/laravel/artisan queue:work redis --sleep=3 --tries=3
- autostart=true
- autorestart=true
- user=lisgroup
- numprocs=8
- redirect_stderr=true
- stdout_logfile=/home/lisgroup/logs/worker.log
复制代码
这个例子里的 numprocs 命令会要求 Supervisor 运行并监控 8 个 queue:work 进程,并且在它们运行失败后重新启动。当然,你必须更改 command 命令的 queue:work redis ,以显示你所选择的队列驱动。还需要修改执行的用户 user=XXX
启动 Supervisor
当这个配置文件被创建后,你需要更新 Supervisor 的配置,并用以下命令来启动该进程:
- sudo supervisorctl reread
- sudo supervisorctl update
- sudo supervisorctl start laravel-worker:*
复制代码
更多有关 Supervisor 的设置与使用,请参考 Supervisor 官方文档。
五、处理失败的任务
有时候你队列中的任务会失败。不要担心,本来事情就不会一帆风顺。Laravel 内置了一个方便的方式来指定任务重试的最大次数。当任务超出这个重试次数后,它就会被插入到 failed_jobs 数据表里面。要创建 failed_jobs 表的迁移文件,你可以用 queue:failed-table 命令,接着使用 migrate Artisan 命令生成 failed_jobs 表:- php artisan queue:failed-table
- php artisan migrate
复制代码
然后运行队列处理器,在调用 queue worker,命令时你应该通过 --tries 参数指定任务的最大重试次数。如果不指定,任务就会永久重试:
- php artisan queue:work redis --tries=3
复制代码
六、清除失败任务
你可以在任务类里直接定义 failed 方法,它能在任务失败时运行任务的清除逻辑。这个地方用来发一条警告给用户或者重置任务执行的操作等再好不过了。导致任务失败的异常信息会被传递到 failed 方法:- namespace App\Jobs;
- use Exception;
- use App\Podcast;
- use App\AudioProcessor;
- use Illuminate\Bus\Queueable;
- use Illuminate\Queue\SerializesModels;
- use Illuminate\Queue\InteractsWithQueue;
- use Illuminate\Contracts\Queue\ShouldQueue;
- class ProcessPodcast implements ShouldQueue
- {
- use InteractsWithQueue, Queueable, SerializesModels;
- protected $podcast;
- /**
- * 创建一个新的任务实例。
- *
- * @param Podcast $podcast
- * @return void
- */
- public function __construct(Podcast $podcast)
- {
- $this->podcast = $podcast;
- }
- /**
- * 执行任务。
- *
- * @param AudioProcessor $processor
- * @return void
- */
- public function handle(AudioProcessor $processor)
- {
- // 处理上传播客...
- }
- /**
- * 要处理的失败任务。
- *
- * @param Exception $exception
- * @return void
- */
- public function failed(Exception $exception)
- {
- // 给用户发送失败通知,等等...
- }
- }
复制代码
|