我认为背景作业真的很方便,无论是用于导入大型CSV文件,从Webhook处理数据,还是许多其他我们可以在没有任何人观看的情况下委派进行处理的其他任务。
在拉拉维尔(Laravel)中,没什么不同。该框架为我们提供了一个功能强大的现成功能,用于队列处理。让我们回顾一下如何运行队列:
php artisan queue:work {connectionName} --queue={queueName} ...
上面,我们有一个非常基本的示例,说明如何开始队列。还有其他几个选择,要了解所有这些选择,建议您检查official documentation。
输入地平线
Horizon于2017年发布,它是用于运行和监视队列的软件包(请记住,无法管理的内容无法管理)。它的任务不是要取代,而是要补充Laravel的队列。
使用Horizon,我们有一种更简单的方法来管理运行队列所需的一切,以及平衡我们队列执行的机制。
一个常见的问题...
我在维护的应用中看到的最常见的问题之一是地平线不足。我的意思是什么?让我们看看:
- 仅将一个工人用于所有队列的项目。
- 记忆管理差。
- 与系统处理的工作数量相比,工人数量不足。
“这是否意味着我不知道如何配置我的队列,Matheusã£o?”
不是那样。每个项目都有其独特性,我要在此处显示的所有配置都取决于系统是否广泛使用队列。
在这篇简短的文章中,我将向您展示如何优化您的视野,以便它可以处理许多工作并顺利执行它们。
默认配置
默认情况下,Horizon只有一个配置的工人:
'defaults' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
'autoScalingStrategy' => 'time',
'maxProcesses' => 3,
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
'timeout' => 60,
'nice' => 0,
],
],
太好了,但是这种配置告诉我们什么?
- 我们的工人将处理
default
队列。 - 在这种情况下,负载平衡不适用,因为我们只有一个队列。
- 我们将最多有三个运行过程。
- 工作将仅执行一次,不允许其他尝试。
- 工作的超时为60秒。
太好了,但是如果我们的需求开始增长怎么办?
向工人添加队列
让我们想象我有一个用于处理电子邮件的队列,另一个用于其他系统作业。很酷,我可以这样做:
'defaults' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['emails', 'default'],
'balance' => 'auto',
'autoScalingStrategy' => 'time',
'maxProcesses' => 3,
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
'timeout' => 60,
'nice' => 0,
],
],
很好,但是我们现在有什么?
- 工人处理的两个队列。
- 排队最多3个进程。
使用此配置,任何需要更多的人都会获得更多的流程。想象一下,电子邮件队列有40个工作,默认队列只有4个工作。Horizon将为emails
队列分配2个进程和default
Queue的1个进程。
在地平线上配置多个工人
现在,让我们进入我们场景的顶峰。让我们想象以下内容:
- 通知(例如,通过Slack)
- 电子邮件发送
- 接收Webhook数据
- CSV数据导入
“那不是太多吗?”
让我们逐步迈进;它将奏效。
优先我们的队列
要开始工作,让我们对我们的队列进行分类:
- 高优先级
- 低优先级
- 默认
- 工作可能需要很长时间才能完成
很棒,现在我有了这些类别,我将使用enum
跟踪它们:
<?php
declare(strict_types=1);
namespace App\Enums;
enum QueuePriority: string
{
case Low = 'low';
case High = 'high';
case LongTimeout = 'long-timeout';
}
请注意,我没有将default
队列添加到此枚举中,因为未分类的作业会直接在队列中转到其中。但是,如果需要ð。
这样,我们可以这样派遣我们的工作:
InviteUser::dispatch($user)->onQueue(
QueuePriority::High->value
);
优雅,不是吗?
调整我们的视野
现在,我们可以创建更多的工人并进一步分开并组织我们的队列:
'defaults' => [
'supervisor-high-priority' => [
'connection' => 'redis',
'queue' => [QueuePriority::High->value],
'balance' => 'auto',
'minProcesses' => 1,
'maxProcesses' => 6,
'balanceMaxShift' => 3,
'balanceCooldown' => 2,
'autoScalingStrategy' => 'size',
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
'timeout' => 60,
'nice' => 0,
],
'supervisor-low-priority' => [
'connection' => 'redis',
'queue' => [QueuePriority::Low->value, 'default'],
'balance' => 'auto',
'minProcesses' => 1,
'maxProcesses' => 3,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'autoScalingStrategy' => 'size',
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
'timeout' => 60,
'nice' => 0,
],
'supervisor-long-timeout' => [
'connection' => 'redis',
'queue' => [QueuePriority::LongTimeout->value],
'balance' => 'auto',
'minProcesses' => 1,
'maxProcesses' => 3,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'autoScalingStrategy' => 'size',
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
'timeout' => 600,
'nice' => 0,
],
],
'environments' => [
'production' => [
'supervisor-high-priority' => [],
'supervisor-low-priority' => [],
'supervisor-long-timeout' => [],
],
'staging' => [
'supervisor-high-priority' => [],
'supervisor-low-priority' => [],
'supervisor-long-timeout' => [],
],
'local' => [
'supervisor-high-priority' => [],
'supervisor-low-priority' => [],
'supervisor-long-timeout' => [],
],
],
我的朋友,我们在这里有什么?现在,我们有3名用于不同队列的工人,并具有以下设置:
主管高优先级
- 照顾高优先级队列。
- 最多6个过程。
- 它将每2分钟开始或终止3个进程(
maxShift
)(coolDown
)。 - 超时设置为1分钟。
主管 - 低优先性
- 管理低优先级和默认队列。
- 最多3个过程。
- 它将每3分钟开始或终止1个进程(
maxShift
)(coolDown
)。 - 超时设置为1分钟。
主管很长
- 处理长期排队。
- 最多3个过程。
- 它将每3分钟开始或终止1个进程(
maxShift
)(coolDown
)。 - 超时设置为10分钟。
这是一个简单的设置,但是完成了工作ð。
将其包裹起来...
现在,我们的队列已配置并准备好处理大量作业。但是请记住,在增加工人数量之前,请确保您的服务器为新工人提供足够的资源。
我呈现的方式,队列本身不会给您的服务器带来问题。但是,例如,如果您使用的是Redis,可能导致问题的原因是由于记忆短缺而看到您的应用程序会下降,但这是另一个对话的主题。
开始小,在此处增加一个过程,另一个过程,根据需要调整超时。切勿全力以赴,最大程度地使用您的服务器可以处理的。逐渐并且谨慎地,您可以在背景处理和应用程序的其余部分之间找到完美的平衡。
小心,直到下一次ð§。