# Laravel Horizon - [介绍](#introduction) - [安装](#installation) - [配置](#configuration) - [仪表盘授权](#dashboard-authentication) - [运行 Horizon](#running-horizon) - [部署 Horizon](#deploying-horizon) - [标签](#tags) - [通知](#notifications) - [Metrics](#metrics) ## 介绍 Horizon 提供了一个漂亮的仪表盘,并且可以通过代码配置你的 Laravel Redis 队列,同时它允许你轻易的监控你的队列系统中诸如任务吞吐量,运行时间和失败任务等关键指标。 所有的配置项都存放在一个简单的配置文件中,从而允许你将它放在团队的协同版本控制中,方便团队协作。
## 安装 > {note} 你应该确保 `queue` 配置文件中设置了 `redis` 队列驱动。 你应该使用 Composer 来安为你的 Laravel 项目安装 Horizon: composer require laravel/horizon 安装完成后,使用 `horizon:install` 发布 Artisan 命令: php artisan horizon:install 你还应该创建 `failed_jobs` 表,Laravel 将使用该表来存储任何 [失败的队列任务](/docs/{{version}}/queues#dealing-with-failed-jobs): php artisan queue:failed-table php artisan migrate ### 配置 发布 Horizon 相关文件后,他的主要配置文件会放在 `config/horizon.php`。你可以在这个文件中配置队列相关选项,并且每个配置项都有详细的使用说明,请详细阅读此文件。 #### 均衡配置 Horizon 提供了三种均衡策略:`simple`,`auto`, 和 `false`。默认的是 `simple` ,会将收到的任务均分给队列进程: 'balance' => 'simple', `auto` 策略会根据当前的工作量调整每个队列的工作进程任务数量。例如:如果 `notifications` 队列有 1000 个待执行任务,但是你的 `render` 队列是空的,Horizon 会分配更多的工作进程给 `notifications` 队列,直到 `notifications` 队列中所有任务执行完成。当配置项 `balance` 配置为 `false` 时,Horizon 会使用 Laravel 默认执行行为,它将按照配置中列出的顺序处理队列任务。 #### 任务修整 `horizon` 配置文件允许你配置应保留最近和失败任务的时间(以分钟为单位)。 默认情况下,最近的任务保留一小时,而失败的任务保留一周: 'trim' => [ 'recent' => 60, 'failed' => 10080, ], ### 仪表盘权限验证 Horizon 仪表盘路由是 `/horizon`。 默认情况下,你只能在 `local` 环境下访问仪表盘。在你的 `app/Providers/HorizonServiceProvider.php` 文件中,有一个 `gate` 方法。这里授权控制 **非本地** 环境中对 Horizon 的访问。 你可以根据需要随意修改此门面,以限制对 Horizon 安装的访问: /** * 注册 Horizon gate 方法 * * gate 决定了谁可以在非本地环境中访问 Horizon。 * * @return void */ protected function gate() { Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ 'taylor@laravel.com', ]); }); } ## 运行 Horizon 当在 `config/horizon.php` 文件中配置好了你的队列执行进程后,你就可以使用 `horizon` Artisan 命令启动 Horizon。只需要一条命令语句即可启动所有配置好的队列进程: php artisan horizon 你也可以使用 `horizon:pause` 和 `horizon:continue` Artisan 命令来暂停或继续执行队列任务: php artisan horizon:pause php artisan horizon:continue 你可以使用 `horizon:terminate` Artisan 命令优雅的终止 Horizon 主进程。Horizon 会把正在执行的任务处理完毕后退出: php artisan horizon:terminate ### 部署 Horizon 如果你将 Horizon 部署到线上服务器时,则需要配置一个进程监控器来检测 `php artisan horizon` 命令,在它意外退出时自动重启。上线新代码时则需要该进程监控器终止 Horizon 进程并以修改后的代码重启 Horizon。 #### Supervisor 配置 如果你使用 Supervisor 进程监控器管理你的 `horizon` 进程,那么以下配置文件则可满足需求: [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 > {tip} 如果你不喜欢自己维护服务器,可以考虑使用 [Laravel Forge](https://forge.laravel.com),Forge 提供了运行一个带有 Horizon 的现代、强大的 Laravel 应用所需要的 PHP7+ 及其他所有环境。 ## 标签 Horizon 允许你对任务分配「标签」,包括邮件,事件广播,通知和队列的事件监听器。事实上,Horizon 会智能并且自动根据任务携带 Eloquent 模型给大多数任务标记标签,如下任务示例: video = $video; } /** * 执行任务 * * @return void */ public function handle() { // } } 如果该队列任务是一个携带 `id` 为 `1` 的 `App\Video` 实例,那么它将自动被标记上 `App\Video:1` 标签。因为 Horizon 会检查任务属性是否具有 Eloquent 模型,如果发现 Eloquent 模型,Horizon 将会智能的用该模型的类名和主键为任务标记上标签: $video = App\Video::find(1); App\Jobs\RenderVideo::dispatch($video); #### 自定义标签 如果你想手动的为队列执行的对象定义标签,你可以给这个类定义一个 `tags` 方法: class RenderVideo implements ShouldQueue { /** * 获取分配给这个任务的标签 * * @return array */ public function tags() { return ['render', 'video:'.$this->video->id]; } } ## 通知 > **Note:** 在使用通知之前,你应该添加 `guzzlehttp/guzzle` Composer 包到你的项目。 在使用 Horizon 配置发送短信通知时,你还应该阅读 [Nexmo 通知驱动的依赖条件](https://laravel.com/docs/{{version}}/notifications#sms-notifications)章节。 如果需要在队列等待时间过长时发起通知,可以在应用的 `AppServiceProvider` 中调用 `Horizon::routeMailNotificationsTo`, `Horizon::routeSlackNotificationsTo`, 和 `Horizon::routeSmsNotificationsTo` 方法: Horizon::routeMailNotificationsTo('example@example.com'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel'); Horizon::routeSmsNotificationsTo('15556667777'); #### 配置等待时间过长的阈值 你可以在 `config/horizon.php` 配置文件中设置等待时间过长的具体秒数。`waits` 配置项可以针对每一个 链接/队列 配置阈值: 'waits' => [ 'redis:default' => 60, ], ## Metrics Horizon 包含一个 Metrics 仪表盘,它可以提供任务和队列等待时间和吞吐量信息,为了填充此仪表盘,你需要配置应用的 [scheduler](/docs/{{version}}/scheduling) 每五分钟运行一次 Horizon 的 `snapshot` Artisan 命令: /** * 定义应用程序的任务调度 * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('horizon:snapshot')->everyFiveMinutes(); }