> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Horizon

> 介绍如何使用 Laravel Horizon 可视化管理与监控 Redis 队列。涵盖仪表盘、平衡策略、Supervisor 配置以及通知。

## 什么是 Horizon

[Laravel Horizon](https://github.com/laravel/horizon) 是 Laravel 官方提供的**专用于 Redis 队列**的监控仪表盘。可以实时查看任务吞吐量、执行时间和失败情况，并通过代码管理 worker 配置。

<Info>
  Horizon 是对队列基础功能的扩展。请先了解[队列与任务](/zh/queues)的基础，再阅读本文。此外，其后端必须是 [Redis](/zh/redis)。
</Info>

```mermaid theme={null}
flowchart LR
    Browser["浏览器"] -->|"/horizon"| Dashboard["Horizon<br>仪表盘"]
    Dashboard -->|"监控与控制"| Horizon["Horizon<br>进程"]
    Horizon -->|"任务管理"| Redis["Redis<br>Queue"]
    Redis -->|"取任务"| Worker1["worker 1"]
    Redis -->|"取任务"| Worker2["worker 2"]
    Redis -->|"取任务"| Worker3["worker 3"]
```

## 安装

<Warning>
  Horizon 使用 Redis 作为队列后端。请确认 `config/queue.php` 中 `QUEUE_CONNECTION` 已设置为 `redis`。目前尚不支持 Redis Cluster。
</Warning>

通过 Composer 安装。

```shell theme={null}
composer require laravel/horizon
```

安装后发布 Horizon 的资源与配置文件。

```shell theme={null}
php artisan horizon:install
```

该命令会生成 `config/horizon.php` 与 `app/Providers/HorizonServiceProvider.php`。

## 配置

### config/horizon.php 结构

`config/horizon.php` 集中管理 worker 的所有配置。核心选项是 `environments`。

```php theme={null}
'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,
        ],
    ],
],
```

<Info>
  Horizon 内部会使用一个名为 `horizon` 的 Redis 连接。请不要在 `config/database.php` 中把这个名字用于其他连接。
</Info>

### Supervisor（监督者）

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

### 默认值

`defaults` 选项可以设置应用于所有 supervisor 的默认值。

```php theme={null}
'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue' => ['default'],
        'balance' => 'auto',
        'tries' => 1,
        'timeout' => 60,
        'maxProcesses' => 1,
    ],
],
```

### 维护模式

当应用处于维护模式时，Horizon 默认不会处理任务。如果要强制处理，可以使用 `force` 选项。

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'force' => true,
        ],
    ],
],
```

### 任务最大重试次数

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'tries' => 10,
        ],
    ],
],
```

`tries` 设为 `0` 时表示允许无限次重试。

### 任务超时

```php theme={null}
'environments' => [
    'production' => [
        'supervisor-1' => [
            'timeout' => 60,
        ],
    ],
],
```

<Warning>
  `timeout` 应比 `config/queue.php` 中的 `retry_after` 短几秒。此外，`auto` 平衡策略下可能会强制中止超过该时间的任务。
</Warning>

### 退避（重试等待时间）

指定发生异常后到下一次重试的等待秒数。

```php theme={null}
// 固定值
'backoff' => 10,

// 阶梯式（指数退避）
'backoff' => [1, 5, 10],
```

## 平衡策略

Horizon 提供三种 worker 平衡策略。

<AccordionGroup>
  <Accordion title="auto（默认）">
    根据队列负载自动调整 worker 数量。通过 `minProcesses` 和 `maxProcesses` 指定范围。

    ```php theme={null}
    'supervisor-1' => [
        'balance' => 'auto',
        'autoScalingStrategy' => 'time', // 或 'size'
        'minProcesses' => 1,
        'maxProcesses' => 10,
        'balanceMaxShift' => 1,
        'balanceCooldown' => 3,
    ],
    ```

    * `time` — 根据清空队列的预计时间进行伸缩
    * `size` — 根据队列内的任务数进行伸缩

    <Info>
      在 `auto` 策略下，队列的顺序并不代表优先级。如果需要强制优先级，请使用多个 supervisor。
    </Info>
  </Accordion>

  <Accordion title="simple">
    固定 worker 数量，均匀分配给指定的队列。

    ```php theme={null}
    'supervisor-1' => [
        'balance' => 'simple',
        'processes' => 10,
        'queue' => ['default', 'notifications'],
    ],
    ```

    上例会为 `default` 和 `notifications` 各分配 5 个进程。
  </Accordion>

  <Accordion title="false（不做平衡）">
    严格按照列举的顺序作为优先级。行为与 Laravel 默认的队列系统类似，但会根据积压情况伸缩 worker 数量。

    ```php theme={null}
    'supervisor-1' => [
        'balance' => false,
        'queue' => ['default', 'notifications'],
        'minProcesses' => 1,
        'maxProcesses' => 10,
    ],
    ```

    `default` 队列的任务始终优先于 `notifications` 队列被处理。
  </Accordion>
</AccordionGroup>

## 仪表盘的授权

Horizon 仪表盘可通过 `/horizon` 路由访问。本地环境默认对所有人开放，但**生产环境**需要通过 Gate 定义来限制访问。

编辑 `app/Providers/HorizonServiceProvider.php` 中的 `gate()` 方法。

```php theme={null}
use App\Models\User;
use Illuminate\Support\Facades\Gate;

protected function gate(): void
{
    Gate::define('viewHorizon', function (User $user) {
        return in_array($user->email, [
            'admin@example.com',
        ]);
    });
}
```

如果无需登录（例如已通过 IP 限制保护），可以把参数改为可选。

```php theme={null}
Gate::define('viewHorizon', function (User $user = null) {
    // 通过 IP 等方式限制的场景
    return true;
});
```

## 启动 Horizon

### 基本命令

```shell theme={null}
# 启动
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` 命令。

```shell theme={null}
npm install --save-dev chokidar
php artisan horizon:listen

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

### 通过 Supervisor 常驻运行

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

#### 安装 Supervisor

```shell theme={null}
sudo apt-get install supervisor
```

#### 创建配置文件

创建 `/etc/supervisor/conf.d/horizon.conf`。

```ini theme={null}
[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
```

<Warning>
  `stopwaitsecs` 需设置为大于最长任务执行时间的值。设置得过小时，Supervisor 会中途强制杀掉任务。
</Warning>

#### 启动 Supervisor

```shell theme={null}
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
```

#### 部署时

每次部署代码后重启 Horizon 以生效。

```shell theme={null}
php artisan horizon:terminate
```

只要 Supervisor 中设置了 `autostart=true` / `autorestart=true`，退出后会自动重启。

## 任务管理

### 标签

Horizon 会自动检测任务关联的 Eloquent 模型，并加上标签。

```php theme={null}
// 接收 Video 模型(id=1) 的任务 → 自动打上 "App\Models\Video:1" 标签
RenderVideo::dispatch(Video::find(1));
```

若要手动定义标签，实现 `tags()` 方法即可。

```php theme={null}
class RenderVideo implements ShouldQueue
{
    /**
     * @return array<int, string>
     */
    public function tags(): array
    {
        return ['render', 'video:'.$this->video->id];
    }
}
```

在事件监听器中，`tags()` 方法会收到事件实例。

```php theme={null}
class SendRenderNotifications implements ShouldQueue
{
    public function tags(VideoRendered $event): array
    {
        return ['video:'.$event->video->id];
    }
}
```

### 静默任务

若不希望某些任务在仪表盘的“已完成任务”列表中显示，可以在 `config/horizon.php` 里将其静默化。

```php theme={null}
'silenced' => [
    App\Jobs\ProcessPodcast::class,
],

// 按标签静默
'silenced_tags' => [
    'notifications',
],
```

也可以实现 `Silenced` 接口。

```php theme={null}
use Laravel\Horizon\Contracts\Silenced;

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

## 指标与监控

Horizon 的指标仪表盘展示任务与队列的吞吐量和执行时间。需要定时执行快照命令来采集数据。

```php theme={null}
// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('horizon:snapshot')->everyFiveMinutes();
```

若要清除全部指标数据，执行以下命令。

```shell theme={null}
php artisan horizon:clear-metrics
```

## 任务失败通知

当队列的等待时间过长时可以接收到通知。可以在 `app/Providers/HorizonServiceProvider.php` 的 `boot()` 方法中配置。

```php theme={null}
use Laravel\Horizon\Horizon;

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

    Horizon::routeMailNotificationsTo('admin@example.com');
    Horizon::routeSlackNotificationsTo('slack-webhook-url', '#ops');
    Horizon::routeSmsNotificationsTo('15556667777');
}
```

### 等待时间阈值

在 `config/horizon.php` 的 `waits` 选项中配置触发通知的等待秒数。

```php theme={null}
'waits' => [
    'redis:critical' => 30,  // 等待超过 30 秒即通知
    'redis:default' => 60,
    'redis:batch' => 120,
],
```

设为 `0` 表示禁用该队列的通知。

## 失败任务的管理

失败任务可以通过 ID 或 UUID 删除。

```shell theme={null}
# 删除指定的失败任务
php artisan horizon:forget 5

# 删除全部失败任务
php artisan horizon:forget --all
```

要清空队列中的任务，可以使用以下命令。

```shell theme={null}
# 清空默认队列
php artisan horizon:clear

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

## 升级

Horizon 主版本升级前，请务必参考[升级指南](https://github.com/laravel/horizon/blob/master/UPGRADE.md)。

## 相关页面

<CardGroup cols={2}>
  <Card title="队列与任务" href="/zh/queues">
    Laravel 队列的基础。任务的创建、派发、批处理与失败处理。
  </Card>

  <Card title="Redis" href="/zh/redis">
    Horizon 后端所需的 Redis 配置与用法。
  </Card>
</CardGroup>


## Related topics

- [缓存](/zh/cache.md)
- [包的版本兼容性管理](/zh/advanced/package-versioning.md)
- [队列与任务](/zh/queues.md)
- [Laravel Sentinel — 路由保护中间件调查](/zh/blog/sentinel-introduction.md)
- [2026 年 4 月 Laravel 更新](/zh/blog/changelog/202604.md)
