Laravel 任务和队列 101:队列连接、使用多个队列以及设置优先级
发布时间:作者:Youghourta Benali
现在您已经了解了本系列文章第一部分中介绍的 Laravel 中任务和队列的基本知识,让我们来学习如何使用不同的队列连接(除了数据库连接之外),如何使用多个不同的队列来处理不同的任务,以及如何将某些任务/队列的优先级设置得更高。
使用 RabbitMQ
虽然 Laravel 社区中选择 Redis 作为数据库以外的队列连接的“默认”选择,但我们将使用 RabbitMQ 来代替。
我选择使用 RabbitMQ 的原因如下
- 与 RabbitMQ 相比,其他队列连接的文档比较完善(请查看 https://laravel.net.cn/docs/6.x/horizon,这是 Laravel 用于 Redis 队列的官方软件包)。
- 根据我的经验,我发现 RabbitMQ 比其他队列连接更出色。
- 如果您正在阅读本文,那么您很有可能是刚刚接触任务和队列的世界,因此最好先专注于学习如何处理它们,而不必过多地关注如何安装 Redis,以及如何在本地机器和生产环境中使其正常工作。使用 RabbitMQ,我们可以利用第三方服务来托管和管理我们的 RabbitMQ 实例。我首选的服务是 cloudAMQP.com。它的免费试用版对于本教程以及许多您将要进行的副项目来说已经足够了(每月 100 万个任务,100 个队列等等)。
设置队列
访问 cloudamqp.com,注册并创建一个 Little Lemur 实例。
创建实例后,您将获得其详细信息,如下所示
现在我们需要让 Laravel 知道我们要将任务推送到 RabbitMQ 而不是数据库。
首先,我们需要添加以下软件包:vladimir-yuldashev/laravel-queue-rabbitmq
composer require vladimir-yuldashev/laravel-queue-rabbitmq
之后,我们需要将以下连接添加到 config/queue.php
文件中
'rabbitmq' => [ 'driver' => 'rabbitmq', 'queue' => env('RABBITMQ_QUEUE', 'default'), 'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class, 'hosts' => [ [ 'host' => env('RABBITMQ_HOST', '127.0.0.1'), 'port' => env('RABBITMQ_PORT', 5672), 'user' => env('RABBITMQ_USER', 'guest'), 'password' => env('RABBITMQ_PASSWORD', 'guest'), 'vhost' => env('RABBITMQ_VHOST', '/'), ], ], 'options' => [ 'ssl_options' => [ 'cafile' => env('RABBITMQ_SSL_CAFILE', null), 'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null), 'local_key' => env('RABBITMQ_SSL_LOCALKEY', null), 'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true), 'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null), ], ], /* * Set to "horizon" if you wish to use Laravel Horizon. */ 'worker' => env('RABBITMQ_WORKER', 'default'), ],
然后我们需要更新 .env
文件,如下所示
QUEUE_CONNECTION=rabbitmqRABBITMQ_DSN=amqp://RABBITMQ_HOST=woodpecker.rmq.cloudamqp.comRABBITMQ_VHOST=ojydhdauRABBITMQ_USER=ojydhdauRABBITMQ_PASSWORD=Bctt-m_WhXrWdNGcb1L5D7D5j-3j-8GcRABBITMQ_QUEUE=jobs
PS: QUEUE_CONNECTION
变量已经存在于 .env
文件中,因此请确保更新现有的变量。
在我们测试新配置之前,让我们执行以下操作
让我们打开 RabbitMQ 管理器,并检查是否已创建任何队列和任务。
如您所见,我们没有任何队列或任务。
现在,在我们发送任何新的请求之前,我们需要重新启动本地 Web 服务器,以便考虑新的 .env
文件更改。
现在,如果您向应用程序发送新的 POST
请求,我们会注意到以下情况
当我们切换到队列选项卡时,我们会注意到已创建了一个新的队列。
请注意,队列的状态为 空闲
,一旦我们执行 queue:work
命令,状态将更改为 正在运行
,并且任务将被消耗。
PS: 当使用 RabbitMQ 时,您无需手动检查队列工作进程是否正在运行,您只需检查队列的状态(如果它们为“空闲”,则表示它们没有运行)。
使用多个队列
现在想象一下,您已经部署了您的应用程序,并将其公开发布。另一个可以从队列中受益的任务是向新注册的用户发送欢迎电子邮件。
您可能想要将此任务委派给队列的原因之一是,您很可能会使用第三方服务来发送电子邮件,并且您不希望让用户等待电子邮件发送完成,然后才能将他们重定向到应用程序仪表板。
这个过程与处理传入的 POST 请求类似,每次我们想要发送一封新电子邮件时,它都会被排队,然后在后台处理。
在这个阶段,您会注意到所有任务都排队在同一个名为 jobs
的队列中(请记住,我们在 .env
文件中有一个变量 RABBITMQ_QUEUE=jobs
)。
如果我们没有指定要调度任务的队列名称,Laravel 就会将它们发送到默认队列。但是我们也可以将每种类型的任务发送到特定的队列。
// This job is sent to the default queue...Job::dispatch(); // This job is sent to the "emails" queue...Job::dispatch()->onQueue('emails');
现在,每当用户注册时,新的 WelcomeEmail 任务就会被调度到 emails
队列。
为了消耗任务,我们有两个选择
我们可以打开一个新选项卡,运行 queue:work
命令,并专门监听这个队列。
php artisan queue:work –queue=emails
或者,我们可以在同一个选项卡中消耗这两个队列,但是这里我们将为每个队列设置优先级。例如,如果我们想先消耗 jobs
队列中的所有任务,然后再处理任何电子邮件,我们可以执行以下操作
php artisan queue:work --queue=jobs,emails
PS: 当您将应用程序部署到生产服务器时,您可能不需要设置优先级,因为我们将分别在后台进程中处理每个队列。
下一步是什么?
如果您已经完成所有步骤,那么您现在就可以将应用程序部署到生产服务器了。
在下一篇文章中,我们将探讨如何在远程服务器上运行工作进程,因为我们不能一直保持终端选项卡打开来消耗任务。
后端开发人员 http://youghourta.com 我开发了
- botmarker.com
- bookmarkingBot.com
- todocol.com
我也是“Laravel 测试 101”的作者 http://laraveltesting101.com