跳转到主要内容

什么是 Horizon

Laravel Horizon 是 Laravel 官方提供的专用于 Redis 队列的监控仪表盘。可以实时查看任务吞吐量、执行时间和失败情况,并通过代码管理 worker 配置。
Horizon 是对队列基础功能的扩展。请先了解队列与任务的基础,再阅读本文。此外,其后端必须是 Redis

安装

Horizon 使用 Redis 作为队列后端。请确认 config/queue.phpQUEUE_CONNECTION 已设置为 redis。目前尚不支持 Redis Cluster。
通过 Composer 安装。
composer require laravel/horizon
安装后发布 Horizon 的资源与配置文件。
php artisan horizon:install
该命令会生成 config/horizon.phpapp/Providers/HorizonServiceProvider.php

配置

config/horizon.php 结构

config/horizon.php 集中管理 worker 的所有配置。核心选项是 environments
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default', 'notifications'],
            'balance' => 'auto',
            'autoScalingStrategy' => 'time',
            'minProcesses' => 1,
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
            'tries' => 3,
            'timeout' => 60,
        ],
    ],

    'local' => [
        'supervisor-1' => [
            // 其他项会从 defaults 部分继承
            'maxProcesses' => 3,
        ],
    ],
],
Horizon 内部会使用一个名为 horizon 的 Redis 连接。请不要在 config/database.php 中把这个名字用于其他连接。

Supervisor(监督者)

每个环境可以有一个或多个“Supervisor”。它们是 worker 组的管理单元,可以在同一个环境下运行多个具有不同队列、平衡策略和进程数的 supervisor。

默认值

defaults 选项可以设置应用于所有 supervisor 的默认值。
'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue' => ['default'],
        'balance' => 'auto',
        'tries' => 1,
        'timeout' => 60,
        'maxProcesses' => 1,
    ],
],

维护模式

当应用处于维护模式时,Horizon 默认不会处理任务。如果要强制处理,可以使用 force 选项。
'environments' => [
    'production' => [
        'supervisor-1' => [
            'force' => true,
        ],
    ],
],

任务最大重试次数

'environments' => [
    'production' => [
        'supervisor-1' => [
            'tries' => 10,
        ],
    ],
],
tries 设为 0 时表示允许无限次重试。

任务超时

'environments' => [
    'production' => [
        'supervisor-1' => [
            'timeout' => 60,
        ],
    ],
],
timeout 应比 config/queue.php 中的 retry_after 短几秒。此外,auto 平衡策略下可能会强制中止超过该时间的任务。

退避(重试等待时间)

指定发生异常后到下一次重试的等待秒数。
// 固定值
'backoff' => 10,

// 阶梯式(指数退避)
'backoff' => [1, 5, 10],

平衡策略

Horizon 提供三种 worker 平衡策略。
根据队列负载自动调整 worker 数量。通过 minProcessesmaxProcesses 指定范围。
'supervisor-1' => [
    'balance' => 'auto',
    'autoScalingStrategy' => 'time', // 或 'size'
    'minProcesses' => 1,
    'maxProcesses' => 10,
    'balanceMaxShift' => 1,
    'balanceCooldown' => 3,
],
  • time — 根据清空队列的预计时间进行伸缩
  • size — 根据队列内的任务数进行伸缩
auto 策略下,队列的顺序并不代表优先级。如果需要强制优先级,请使用多个 supervisor。
固定 worker 数量,均匀分配给指定的队列。
'supervisor-1' => [
    'balance' => 'simple',
    'processes' => 10,
    'queue' => ['default', 'notifications'],
],
上例会为 defaultnotifications 各分配 5 个进程。
严格按照列举的顺序作为优先级。行为与 Laravel 默认的队列系统类似,但会根据积压情况伸缩 worker 数量。
'supervisor-1' => [
    'balance' => false,
    'queue' => ['default', 'notifications'],
    'minProcesses' => 1,
    'maxProcesses' => 10,
],
default 队列的任务始终优先于 notifications 队列被处理。

仪表盘的授权

Horizon 仪表盘可通过 /horizon 路由访问。本地环境默认对所有人开放,但生产环境需要通过 Gate 定义来限制访问。 编辑 app/Providers/HorizonServiceProvider.php 中的 gate() 方法。
use App\Models\User;
use Illuminate\Support\Facades\Gate;

protected function gate(): void
{
    Gate::define('viewHorizon', function (User $user) {
        return in_array($user->email, [
            '[email protected]',
        ]);
    });
}
如果无需登录(例如已通过 IP 限制保护),可以把参数改为可选。
Gate::define('viewHorizon', function (User $user = null) {
    // 通过 IP 等方式限制的场景
    return true;
});

启动 Horizon

基本命令

# 启动
php artisan horizon

# 暂停 / 恢复
php artisan horizon:pause
php artisan horizon:continue

# 暂停 / 恢复指定的 supervisor
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1

# 查看状态
php artisan horizon:status
php artisan horizon:supervisor-status supervisor-1

# 优雅关闭
php artisan horizon:terminate

本地开发:自动重启

要在检测到文件变更时自动重启 Horizon,可以使用 horizon:listen 命令。
npm install --save-dev chokidar
php artisan horizon:listen

# Docker / Vagrant 环境下
php artisan horizon:listen --poll

通过 Supervisor 常驻运行

生产环境中,通过 Supervisor 让 Horizon 常驻运行。

安装 Supervisor

sudo apt-get install supervisor

创建配置文件

创建 /etc/supervisor/conf.d/horizon.conf
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/example.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/horizon.log
stopwaitsecs=3600
stopwaitsecs 需设置为大于最长任务执行时间的值。设置得过小时,Supervisor 会中途强制杀掉任务。

启动 Supervisor

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon

部署时

每次部署代码后重启 Horizon 以生效。
php artisan horizon:terminate
只要 Supervisor 中设置了 autostart=true / autorestart=true,退出后会自动重启。

任务管理

标签

Horizon 会自动检测任务关联的 Eloquent 模型,并加上标签。
// 接收 Video 模型(id=1) 的任务 → 自动打上 "App\Models\Video:1" 标签
RenderVideo::dispatch(Video::find(1));
若要手动定义标签,实现 tags() 方法即可。
class RenderVideo implements ShouldQueue
{
    /**
     * @return array<int, string>
     */
    public function tags(): array
    {
        return ['render', 'video:'.$this->video->id];
    }
}
在事件监听器中,tags() 方法会收到事件实例。
class SendRenderNotifications implements ShouldQueue
{
    public function tags(VideoRendered $event): array
    {
        return ['video:'.$event->video->id];
    }
}

静默任务

若不希望某些任务在仪表盘的“已完成任务”列表中显示,可以在 config/horizon.php 里将其静默化。
'silenced' => [
    App\Jobs\ProcessPodcast::class,
],

// 按标签静默
'silenced_tags' => [
    'notifications',
],
也可以实现 Silenced 接口。
use Laravel\Horizon\Contracts\Silenced;

class ProcessPodcast implements ShouldQueue, Silenced
{
    use Queueable;
    // ...
}

指标与监控

Horizon 的指标仪表盘展示任务与队列的吞吐量和执行时间。需要定时执行快照命令来采集数据。
// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('horizon:snapshot')->everyFiveMinutes();
若要清除全部指标数据,执行以下命令。
php artisan horizon:clear-metrics

任务失败通知

当队列的等待时间过长时可以接收到通知。可以在 app/Providers/HorizonServiceProvider.phpboot() 方法中配置。
use Laravel\Horizon\Horizon;

public function boot(): void
{
    parent::boot();

    Horizon::routeMailNotificationsTo('[email protected]');
    Horizon::routeSlackNotificationsTo('slack-webhook-url', '#ops');
    Horizon::routeSmsNotificationsTo('15556667777');
}

等待时间阈值

config/horizon.phpwaits 选项中配置触发通知的等待秒数。
'waits' => [
    'redis:critical' => 30,  // 等待超过 30 秒即通知
    'redis:default' => 60,
    'redis:batch' => 120,
],
设为 0 表示禁用该队列的通知。

失败任务的管理

失败任务可以通过 ID 或 UUID 删除。
# 删除指定的失败任务
php artisan horizon:forget 5

# 删除全部失败任务
php artisan horizon:forget --all
要清空队列中的任务,可以使用以下命令。
# 清空默认队列
php artisan horizon:clear

# 清空指定队列
php artisan horizon:clear --queue=emails

升级

Horizon 主版本升级前,请务必参考升级指南

相关页面

队列与任务

Laravel 队列的基础。任务的创建、派发、批处理与失败处理。

Redis

Horizon 后端所需的 Redis 配置与用法。
最后修改于 2026年7月13日