跳至内容

Laravel Horizo​​n

介绍

在深入研究 Laravel Horizo​​n 之前,你应该熟悉 Laravel 的基础队列服务。Horizo​​n 为 Laravel 的队列添加了额外的功能,如果你还不熟悉 Laravel 提供的基本队列功能,这些功能可能会让你感到困惑。

Laravel Horizo​​n为基于 Laravel 的Redis 队列提供了美观的仪表盘和代码驱动的配置。Horizo​​n 可让您轻松监控队列系统的关键指标,例如作业吞吐量、运行时间和作业失败情况。

使用 Horizo​​n 时,所有队列工作器配置都存储在一个简单的配置文件中。通过在版本控制文件中定义应用程序的工作器配置,您可以在部署应用程序时轻松地扩展或修改应用程序的队列工作器。

安装

Laravel Horizo​​n 要求使用Redisredis来支持队列。因此,请确保在应用程序的config/queue.php配置文件中已设置队列连接。

您可以使用 Composer 包管理器将 Horizo​​n 安装到您的项目中:

1composer require laravel/horizon

安装 Horizo​​n 后,使用horizon:installArtisan 命令发布其资产:

1php artisan horizon:install

配置

发布 Horizo​​n 的资源后,其主配置文件将位于config/horizon.php。此配置文件允许您配置应用程序的队列工作器选项。每个配置选项都包含其用途的描述,因此请务必仔细研究此文件。

Horizo​​n 使用内部命名的 Redis 连接horizon。此 Redis 连接名称是保留的,不应在配置文件中将其分配给其他 Redis 连接,也不应将其作为配置文件中选项database.php的值usehorizon.php

环境

安装完成后,您应该熟悉的主要 Horizo​​n 配置选项是environments配置选项。此配置选项是一个环境数组,其中包含应用程序在其上运行的环境,并定义了每个环境的工作进程选项。默认情况下,此条目包含一个productionlocal环境。但是,您可以根据需要自由添加更多环境:

1'environments' => [
2 'production' => [
3 'supervisor-1' => [
4 'maxProcesses' => 10,
5 'balanceMaxShift' => 1,
6 'balanceCooldown' => 3,
7 ],
8 ],
9 
10 'local' => [
11 'supervisor-1' => [
12 'maxProcesses' => 3,
13 ],
14 ],
15],

您还可以定义一个通配符环境(*),当找不到其他匹配的环境时将使用它:

1'environments' => [
2 // ...
3 
4 '*' => [
5 'supervisor-1' => [
6 'maxProcesses' => 3,
7 ],
8 ],
9],

当你启动 Horizo​​n 时,它将使用应用程序所在环境的工作进程配置选项。通常,环境由APP_ENV 环境变量的值决定。例如,默认的localHorizo​​n 环境配置为启动三个工作进程,并自动平衡分配给每个队列的工作进程数量。默认production环境配置为最多启动 10 个工作进程,并自动平衡分配给每个队列的工作进程数量。

您应该确保配置文件environments的部分包含您计划运行 Horizo​​n 的每个环境horizon的条目。

主管

正如您在 Horizo​​n 的默认配置文件中所见,每个环境可以包含一个或多个“主管”。默认情况下,配置文件将此主管定义为supervisor-1;但是,您可以随意命名主管。每个主管本质上负责“监管”一组工作进程,并负责在队列之间平衡工作进程。

如果您想定义一组新的工作进程在给定环境中运行,可以向该环境添加额外的主管进程。如果您想为应用程序使用的给定队列定义不同的平衡策略或工作进程数量,也可以选择这样做。

维护模式

当你的应用程序处于维护模式时,排队的作业将不会被 Horizo​​n 处理,除非在 Horizo​​n 配置文件中force定义了主管的选项:true

1'environments' => [
2 'production' => [
3 'supervisor-1' => [
4 // ...
5 'force' => true,
6 ],
7 ],
8],

默认值

在 Horizo​​n 的默认配置文件中,你会注意到一个defaults配置选项。此配置选项指定了应用程序supervisor的默认值。supervisor 的默认配置值将合并到每个环境的 supervisor 配置中,从而避免在定义 supervisor 时进行不必要的重复配置。

平衡策略

与 Laravel 的默认队列系统不同,Horizo​​n 允许你从三种工作进程平衡策略中进行选择:simpleautofalse。该simple策略将传入的任务均匀地分配给各个工作进程:

1'balance' => 'simple',

auto策略是配置文件的默认策略,它会根据队列的当前工作负载调整每个队列的工作进程数量。例如,如果您的notifications队列中有 1,000 个待处理作业,而render队列为空,Horizo​​n 会向队列分配更多工作进程,notifications直到队列为空。

使用该auto策略时,您可以定义minProcessesmaxProcesses配置选项来控制每个队列的最小进程数以及 Horizo​​n 中工作进程的最大数量,以便可以将其扩大或缩小到:

1'environments' => [
2 'production' => [
3 'supervisor-1' => [
4 'connection' => 'redis',
5 'queue' => ['default'],
6 'balance' => 'auto',
7 'autoScalingStrategy' => 'time',
8 'minProcesses' => 1,
9 'maxProcesses' => 10,
10 'balanceMaxShift' => 1,
11 'balanceCooldown' => 3,
12 'tries' => 3,
13 ],
14 ],
15],

配置autoScalingStrategy值决定 Horizo​​n 是否根据清除队列所需的总时间(time策略)或队列上的作业总数(size策略)向队列分配更多工作进程。

balanceMaxShift和配置balanceCooldown决定了 Horizo​​n 扩展以满足工作需求的速度。在上面的示例中,每三秒最多会创建或销毁一个新进程。您可以根据应用程序的需求随意调整这些值。

balance选项设置为时false,将使用默认的 Laravel 行为,其中队列按照配置中列出的顺序进行处理。

仪表板授权

Horizo​​n 仪表板可以通过路由访问/horizon。默认情况下,您只能在local环境中访问此仪表板。但是,在您的app/Providers/HorizonServiceProvider.php文件中,有一个授权门定义。此授权门控制在非本地环境中对 Horizo​​n 的访问。您可以根据需要随意修改此门,以限制对 Horizo​​n 安装的访问:

1/**
2 * Register the Horizon gate.
3 *
4 * This gate determines who can access Horizon in non-local environments.
5 */
6protected function gate(): void
7{
8 Gate::define('viewHorizon', function (User $user) {
9 return in_array($user->email, [
10 'taylor@laravel.com',
11 ]);
12 });
13}

替代身份验证策略

请记住,Laravel 会自动将已验证的用户注入到 gate 闭包中。如果您的应用程序通过其他方式(例如 IP 限制)提供 Horizo​​n 安全性,那么您的 Horizo​​n 用户可能无需“登录”。因此,您需要将function (User $user)上面的闭包签名更改为 ,function (User $user = null)以强制 Laravel 不再要求身份验证。

沉默的工作

有时,您可能不想查看由应用程序或第三方软件包调度的某些作业。您可以将这些作业静默,以避免它们占用“已完成作业”列表中的空间。首先,将作业的类名添加到silenced应用程序horizon配置文件中的配置选项中:

1'silenced' => [
2 App\Jobs\ProcessPodcast::class,
3],

或者,您希望静默的作业可以实现该Laravel\Horizon\Contracts\Silenced接口。如果作业实现了此接口,即使它不在silenced配置数组中,它也会自动被静默:

1use Laravel\Horizon\Contracts\Silenced;
2 
3class ProcessPodcast implements ShouldQueue, Silenced
4{
5 use Queueable;
6 
7 // ...
8}

升级 Horizo​​n

升级到 Horizo​​n 的新主要版本时,仔细阅读升级指南非常重要

奔跑Horizon

在应用程序的配置文件中配置好主管进程和工作进程后config/horizon.php,就可以使用horizonArtisan 命令启动 Horizo​​n 了。这条命令将启动当前环境中所有已配置的工作进程:

1php artisan horizon

您可以暂停 Horizo​​n 进程并指示它使用horizon:pausehorizon:continueArtisan 命令继续处理作业:

1php artisan horizon:pause
2 
3php artisan horizon:continue

您还可以使用和Artisan 命令暂停和继续特定的 Horizo​​n主管horizon:pause-supervisorhorizon:continue-supervisor

1php artisan horizon:pause-supervisor supervisor-1
2 
3php artisan horizon:continue-supervisor supervisor-1

您可以使用 Artisan 命令检查 Horizo​​n 进程的当前状态horizon:status

1php artisan horizon:status

您可以使用Artisan 命令检查特定 Horizo​​n主管的当前状态horizon:supervisor-status

1php artisan horizon:supervisor-status supervisor-1

您可以使用 Artisan 命令优雅地终止 Horizo​​n 进程horizon:terminate。所有当前正在处理的作业都将完成,然后 Horizo​​n 将停止执行:

1php artisan horizon:terminate

部署 Horizo​​n

当您准备将 Horizo​​n 部署到应用程序的实际服务器时,您应该配置一个进程监视器来监视命令php artisan horizon,并在命令意外退出时重新启动它。不用担心,我们将在下面讨论如何安装进程监视器。

在应用程序的部署过程中,您应该指示 Horizo​​n 进程终止,以便进程监视器重新启动它并接收您的代码更改:

1php artisan horizon:terminate

安装 Supervisor

Supervisor 是 Linux 操作系统的进程监视器,horizon如果进程停止执行,它将自动重启。要在 Ubuntu 上安装 Supervisor,可以使用以下命令。如果您使用的不是 Ubuntu,也可以使用操作系统的包管理器来安装 Supervisor:

1sudo apt-get install supervisor

如果您觉得自己配置 Supervisor 听起来很麻烦,请考虑使用Laravel Cloud,它可以管理您的 Laravel 应用程序的后台进程。

主管配置

Supervisor 的配置文件通常存储在服务器的/etc/supervisor/conf.d目录中。在这个目录中,你可以创建任意数量的配置文件,用于指示 Supervisor 如何监控你的进程。例如,让我们创建一个horizon.conf启动并监控horizon进程的文件:

1[program:horizon]
2process_name=%(program_name)s
3command=php /home/forge/example.com/artisan horizon
4autostart=true
5autorestart=true
6user=forge
7redirect_stderr=true
8stdout_logfile=/home/forge/example.com/horizon.log
9stopwaitsecs=3600

在定义 Supervisor 配置时,应确保 的值stopwaitsecs大于运行时间最长的作业所消耗的秒数。否则,Supervisor 可能会在作业处理完成之前将其终止。

虽然上述示例适用于基于 Ubuntu 的服务器,但 Supervisor 配置文件的预期位置和文件扩展名可能因其他服务器操作系统而异。请参阅服务器的文档以获取更多信息。

启动主管

一旦创建了配置文件,您就可以使用以下命令更新 Supervisor 配置并启动受监控的进程:

1sudo supervisorctl reread
2 
3sudo supervisorctl update
4 
5sudo supervisorctl start horizon

有关运行 Supervisor 的更多信息,请查阅Supervisor 文档

标签

Horizo​​n 允许您为作业分配“标签”,包括可邮寄邮件、广播事件、通知和队列事件监听器。实际上,Horizo​​n 会根据作业所附加的 Eloquent 模型,智能地自动标记大多数作业。例如,查看以下作业:

1<?php
2 
3namespace App\Jobs;
4 
5use App\Models\Video;
6use Illuminate\Contracts\Queue\ShouldQueue;
7use Illuminate\Foundation\Queue\Queueable;
8 
9class RenderVideo implements ShouldQueue
10{
11 use Queueable;
12 
13 /**
14 * Create a new job instance.
15 */
16 public function __construct(
17 public Video $video,
18 ) {}
19 
20 /**
21 * Execute the job.
22 */
23 public function handle(): void
24 {
25 // ...
26 }
27}

App\Models\Video如果此作业与具有id属性的实例一起排队1,它将自动收到标签App\Models\Video:1。这是因为 Horizo​​n 会在作业的属性中搜索任何 Eloquent 模型。如果找到 Eloquent 模型,Horizo​​n 将使用模型的类名和主键智能地标记该作业:

1use App\Jobs\RenderVideo;
2use App\Models\Video;
3 
4$video = Video::find(1);
5 
6RenderVideo::dispatch($video);

手动标记作业

如果您想要手动定义某个可排队对象的标签,您可以tags在类上定义一个方法:

1class RenderVideo implements ShouldQueue
2{
3 /**
4 * Get the tags that should be assigned to the job.
5 *
6 * @return array<int, string>
7 */
8 public function tags(): array
9 {
10 return ['render', 'video:'.$this->video->id];
11 }
12}

手动标记事件监听器

当检索排队事件监听器的标签时,Horizo​​n 会自动将事件实例传递给该tags方法,从而允许您将事件数据添加到标签中:

1class SendRenderNotifications implements ShouldQueue
2{
3 /**
4 * Get the tags that should be assigned to the listener.
5 *
6 * @return array<int, string>
7 */
8 public function tags(VideoRendered $event): array
9 {
10 return ['video:'.$event->video->id];
11 }
12}

通知

配置 Horizo​​n 发送 Slack 或 SMS 通知时,您应该查看相关通知渠道的先决条件

如果您希望在某个队列的等待时间较长时收到通知,可以使用Horizon::routeMailNotificationsToHorizon::routeSlackNotificationsTo和方法。您可以从应用程序的 方法Horizon::routeSmsNotificationsTo中调用这些方法bootApp\Providers\HorizonServiceProvider

1/**
2 * Bootstrap any application services.
3 */
4public function boot(): void
5{
6 parent::boot();
7 
8 Horizon::routeSmsNotificationsTo('15556667777');
9 Horizon::routeMailNotificationsTo('example@example.com');
10 Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
11}

配置通知等待时间阈值

您可以在应用程序的配置文件中配置“长时间等待”的秒数config/horizon.phpwaits此文件中的配置选项允许您控制每个连接/队列组合的长时间等待阈值。任何未定义的连接/队列组合将默认为 60 秒的长时间等待阈值:

1'waits' => [
2 'redis:critical' => 30,
3 'redis:default' => 60,
4 'redis:batch' => 120,
5],

指标

Horizo​​n 包含一个指标仪表盘,提供有关作业和队列等待时间以及吞吐量的信息。为了填充此仪表盘,您应该snapshot在应用程序的routes/console.php文件中将 Horizo​​n 的 Artisan 命令配置为每五分钟运行一次:

1use Illuminate\Support\Facades\Schedule;
2 
3Schedule::command('horizon:snapshot')->everyFiveMinutes();

删除失败的作业

如果您想删除失败的作业,可以使用该horizon:forget命令。该horizon:forget命令接受失败作业的 ID 或 UUID 作为其唯一参数:

1php artisan horizon:forget 5

如果您想删除所有失败的作业,您可以--allhorizon:forget命令提供以下选项:

1php artisan horizon:forget --all

清除队列中的作业

如果您想要从应用程序的默认队列中删除所有作业,可以使用horizon:clearArtisan 命令执行此操作:

1php artisan horizon:clear

您可以提供queue从特定队列中删除作业的选项:

1php artisan horizon:clear --queue=emails