Laravel Queues 队列应用实战 (2)

队列,其实与业务代码无关,而是一种运行机制:首先从 缓存数据 中,定时拉取要执行的 任务,然后在后台执行。如果执行失败,可以将此 任务 重新放回,待下一次重新执行;若执行成功,则将其释放,任务结束。这个运行机制的运转,是由 Laravel 框架维护的,我们无需写任何代码。

我们要写的只是任务,将我们要执行的业务代码,放到任务中,再分发给队列,此任务就会自动执行。

那队列从哪里得知有任务要执行呢,又如何记录任务执行失败的信息呢?其实,我上面说的 缓存数据,就是队列获取任务信息的地方,它可以是 数据库,也可以存储在 redis 里。而且,如果任务执行失败,Laravel 也会将失败信息,保存在数据库中。

此例中,我们采取用数据库,记录任务信息,可以方便的看到任务信息的直观数据。正式上线时,当然可以采用 redis,以实现更高的执行效率,毕竟一个与硬盘打交道,一个与内存打交道,谁快谁慢不言而喻。

首先,执行下面的 artisan 命令,创建2张表:jobs 和 failed_jobs,以存储 任务信息 和 失败信息。

php artisan queue:table php artisan queue:failed-table php artisan migrate

然后,我们要配置队列的连接方式,也就是你到底要从 数据库 还是 redis 中,去获取任务信息。打开 config/queue.php 配置文件,在最上面,你会发现默认连接:'default' => env('QUEUE_CONNECTION', 'sync'),可以看到,配置先从 .env 文件中读取,如若没有,则默认为 sync。我们可以打开 .env,在其中添加或修改为 QUEUE_CONNECTION=database,如果你用 redis 作为默认连接,则配置为 QUEUE_CONNECTION=redis【注意,用 redis 方式,要安装 predis PHP扩展包】。而那个 sync 的默认配置,则代表默认以同步的方式,执行任务,也就是说,任务分发出去以后,不入队列,而是立即在当前进程中同步执行,这跟你正常在主程序中执行业务代码没啥区别,任务会阻塞当前进程。

做好以上配置后,我们可以创建一个任务,写上我们的业务代码,可执行以下 artisan 命令,快速创建任务代码模版类:

php artisan make:job TestJob

我们创建了一个叫 TestJob 的任务类,初始代码长这样:

<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class TestJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * Execute the job. * * @return void */ public function handle() { } }

我们只需要将业务代码,放进 handle() 中即可,比如,我们简单的在其中打点日志,人为的将任务放回队列,让其30秒后继续执行,并设置最大重试次数:

<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Support\Facades\Log; class TestJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries = 3; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * Execute the job. * * @return void */ public function handle() { Log::info('TestJob handle'); Log::info('TestJob release'); $this->release(30); Log::info('TestJob end'); } }

注意 public $tries = 3;,是设置此任务最多尝试执行的次数,并且我们在 handle() 中通过 $this->release(30);,人为的将其放回队列,让其30秒后再试。

下面,我们就需要开启队列了,前面说过,队列的运行机制,是由 Laravel 自动控制的,我们只需通过下面的 artisan 命令,启动队列:

php artisan queue:work

好了,一个队列进程就会启动,并不停的查询 jobs 数据表中,是否有任务要执行。

下面,我们在某个 Controller 中,将上面写的 TestJob 分发给队列,让其自动后台异步执行:

class IndexController extends Controller { public function test(Request $request) { \App\Jobs\TestJob::dispatch(); } }

通过浏览器,访问此控制器的路由地址,触发其中的任务分发,你就会在控制台上看到任务执行的信息输出,并且会在 jobs 数据表中,查询到当前正在执行的任务信息:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspdzp.html