Skip to content

Laravel Horizon

介绍

Horizon 为您的 Laravel 驱动的 Redis 队列提供了一个美观的仪表板和代码驱动的配置。Horizon 允许您轻松监控队列系统的关键指标,如作业吞吐量、运行时间和作业失败。

所有的工作者配置都存储在一个简单的配置文件中,使您的配置可以保留在源代码控制中,便于整个团队协作。

安装

exclamation

您应确保在 queue 配置文件中将队列连接设置为 redis

您可以使用 Composer 将 Horizon 安装到您的 Laravel 项目中:

php
composer require laravel/horizon ~3.0

安装 Horizon 后,使用 horizon:install Artisan 命令发布其资产:

php
php artisan horizon:install

配置

发布 Horizon 的资产后,其主要配置文件将位于 config/horizon.php。此配置文件允许您配置工作者选项,每个配置选项都包含其目的的描述,因此请务必仔细查看此文件。

exclamation

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

平衡选项

Horizon 允许您从三种平衡策略中进行选择:simpleautofalsesimple 策略是配置文件的默认设置,将传入作业均匀分配到各个进程:

php
'balance' => 'simple',

auto 策略根据队列的当前工作负载调整每个队列的工作者进程数量。例如,如果您的 notifications 队列有 1,000 个等待作业,而您的 render 队列为空,Horizon 将为您的 notifications 队列分配更多的工作者,直到它为空。当 balance 选项设置为 false 时,将使用默认的 Laravel 行为,即按配置中列出的顺序处理队列。

使用 auto 策略时,您可以定义 minProcessesmaxProcesses 配置选项,以控制 Horizon 应该扩展和缩减到的最小和最大进程数。minProcesses 值指定每个队列的最小进程数,而 maxProcesses 值指定所有队列的最大进程数:

php
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default'],
            'balance' => 'auto',
            'minProcesses' => 1,
            'maxProcesses' => 10,
            'tries' => 3,
        ],
    ],
],

作业修剪

horizon 配置文件允许您配置最近和失败作业应保留多长时间(以分钟为单位)。默认情况下,最近的作业保留一小时,而失败的作业保留一周:

php
'trim' => [
    'recent' => 60,
    'failed' => 10080,
],

仪表板授权

Horizon 在 /horizon 处公开一个仪表板。默认情况下,您只能在 local 环境中访问此仪表板。在您的 app/Providers/HorizonServiceProvider.php 文件中,有一个 gate 方法。此授权门控控制在非本地环境中访问 Horizon 的权限。您可以根据需要修改此门控以限制对 Horizon 安装的访问:

php
/**
 * 注册 Horizon 门控。
 *
 * 此门控决定谁可以在非本地环境中访问 Horizon。
 *
 * @return void
 */
protected function gate()
{
    Gate::define('viewHorizon', function ($user) {
        return in_array($user->email, [
            'taylor@laravel.com',
        ]);
    });
}
exclamation

请记住,Laravel 会自动将已认证的用户注入到 Gate 中。如果您的应用程序通过其他方法(如 IP 限制)提供 Horizon 安全性,则您的 Horizon 用户可能不需要“登录”。因此,您需要将上面的 function ($user) 更改为 function ($user = null),以强制 Laravel 不要求身份验证。

升级 Horizon

升级到 Horizon 的新主要版本时,您需要仔细查看升级指南

此外,您应该重新发布 Horizon 的资产:

php
php artisan horizon:assets

运行 Horizon

一旦您在 config/horizon.php 配置文件中配置了您的工作者,您可以使用 horizon Artisan 命令启动 Horizon。此单个命令将启动您配置的所有工作者:

php
php artisan horizon

您可以暂停 Horizon 进程,并使用 horizon:pausehorizon:continue Artisan 命令指示其继续处理作业:

php
php artisan horizon:pause

php artisan horizon:continue

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

php
php artisan horizon:status

您可以使用 horizon:terminate Artisan 命令优雅地终止您机器上的主 Horizon 进程。Horizon 当前正在处理的任何作业将完成,然后 Horizon 将退出:

php
php artisan horizon:terminate

部署 Horizon

如果您将 Horizon 部署到实时服务器,您应该配置一个进程监视器来监视 php artisan horizon 命令,并在其意外退出时重新启动它。当将新代码部署到服务器时,您需要指示主 Horizon 进程终止,以便您的进程监视器可以重新启动它并接收您的代码更改。

安装 Supervisor

Supervisor 是 Linux 操作系统的进程监视器,如果 horizon 进程失败,它将自动重新启动。要在 Ubuntu 上安装 Supervisor,您可以使用以下命令:

php
sudo apt-get install supervisor
lightbulb

如果自己配置 Supervisor 听起来很复杂,可以考虑使用 Laravel Forge,它会自动为您的 Laravel 项目安装和配置 Supervisor。

Supervisor 配置

Supervisor 配置文件通常存储在 /etc/supervisor/conf.d 目录中。在此目录中,您可以创建任意数量的配置文件,指示 Supervisor 如何监视您的进程。例如,让我们创建一个 horizon.conf 文件来启动和监视一个 horizon 进程:

php
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/app.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/app.com/horizon.log
stopwaitsecs=3600
exclamation

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

启动 Supervisor

创建配置文件后,您可以使用以下命令更新 Supervisor 配置并启动进程:

php
sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start horizon

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

标签

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

php
<?php

namespace App\Jobs;

use App\Video;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class RenderVideo implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * 视频实例。
     *
     * @var \App\Video
     */
    public $video;

    /**
     * 创建一个新的作业实例。
     *
     * @param  \App\Video  $video
     * @return void
     */
    public function __construct(Video $video)
    {
        $this->video = $video;
    }

    /**
     * 执行作业。
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

如果此作业使用 id1App\Video 实例排队,它将自动接收标签 App\Video:1。这是因为 Horizon 将检查作业的属性以查找任何 Eloquent 模型。如果找到 Eloquent 模型,Horizon 将使用模型的类名和主键智能地标记作业:

php
$video = App\Video::find(1);

App\Jobs\RenderVideo::dispatch($video);

手动标记

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

php
class RenderVideo implements ShouldQueue
{
    /**
     * 获取应分配给作业的标签。
     *
     * @return array
     */
    public function tags()
    {
        return ['render', 'video:'.$this->video->id];
    }
}

通知

lightbulb

在配置 Horizon 发送 Slack 或 SMS 通知时,您应查看相关通知驱动程序的先决条件

如果您希望在队列等待时间过长时收到通知,可以使用 Horizon::routeMailNotificationsToHorizon::routeSlackNotificationsToHorizon::routeSmsNotificationsTo 方法。您可以从应用程序的 HorizonServiceProvider 中调用这些方法:

php
Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
Horizon::routeSmsNotificationsTo('15556667777');

配置通知等待时间阈值

您可以在 config/horizon.php 配置文件中配置多少秒被视为“长等待”。此文件中的 waits 配置选项允许您控制每个连接/队列组合的长等待阈值:

php
'waits' => [
    'redis:default' => 60,
],

指标

Horizon 包含一个指标仪表板,提供有关作业和队列等待时间和吞吐量的信息。为了填充此仪表板,您应配置 Horizon 的 snapshot Artisan 命令通过应用程序的调度器每五分钟运行一次:

php
/**
 * 定义应用程序的命令调度。
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('horizon:snapshot')->everyFiveMinutes();
}