Laravel 队列监控面板 - Horizon

介绍

Horizon 提供了一个漂亮的仪表盘,并且可以通过代码配置你的 Laravel Redis 队列,同时能够让你轻松地监控你的队列系统中诸如任务吞吐量,运行时间和失败任务等关键指标。

所有配置项都存放在一个简单的配置文件中,应当把它放进团队能够协同维护的版本控制中。

安装

{note} 由于 Horizon 中用了异步处理信号,所以安装扩展包需要 PHP 环境在 7.1 以上。

你应该用 Composer 包管理工具来给你的 Laravel 项目安装 Horizon。

  1. composer require laravel/horizon

安装完成后,使用 Artisan 命令来发布它的相关文件:

  1. php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"

配置

发布 Horizon 的相关文件后,它的主要配置文件会放在 config/horizon.php. 你可以在这个文件中配置队列工作进程相关的选项,并且每个配置项都有详细的使用说明,所以请详细的阅读此文件。

负载均衡配置

Horizon 提供了三种均衡策略: simpleauto, 和 false。默认策略是 simple,会将接收到的任务均分给队列进程:

  1. 'balance' => 'simple',

auto 策略会根据当前的工作量调整每个队列的工作进程任务数量。例如:如果 notifications 队列有 1000 个待执行任务,但是你的 render 队列是空的,Horizon 会分配更多工作进程给 notifications 队列,直到 notifications 队列中所有任务执行。当配置项 balance 设置为 false 时,Horizon 会使用 Laravel 默认执行行为,它将按照配置中列出的顺序处理队列任务。

仪表盘权限验证

Horizon 仪表盘的路由是 /horizon。默认情况下,你只能在 local 环境中访问仪表盘。我们可以使用 Horizon::auth 方法给仪表盘定义更具体的访问策略。 auth 方法接受一个回调函数作为参数,该回调函数应当返回 truefalse 以确认用户是否有权限访问仪表盘。通常情况下你应当在 AppServiceProviderboot 方法中调用:

  1. Horizon::auth(function ($request) {
  2. // return true / false;
  3. });

运行 Horizon

当你在 config/horizon.php 文件中配置好了你的队列执行进程后,你就可以用 horizon Artisan 命令启动你的 Horizon。只需一条命令语句即可启动所有配置好的队列执行进程。

  1. php artisan horizon

你也可以用 horizon:pausehorizon:continue Artisan 命令来暂停或继续执行队列任务。:

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

horizon:terminate Artisan 命令可以优雅的终止 Horizon 主进程。Horizon 会在把正在执行的所有任务处理完毕后退出:

  1. php artisan horizon:terminate

部署 Horizon

如果你将 Horizon 部署到线上服务器时,则需要配置一个进程监控器来监测 php artisan horizon 命令,在它意外退出时自动重启。上线新代码时则需要该进程监控器终止 Horizon 进程并以修改后的代码重启 Horizon。

Supervisor 配置

如果你使用 Supervisor 进程监控器管理你的 horizon 进程,那么以下配置文件则可以满足需求。

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

{tip} 如果你不喜欢自己维护服务器,可以考虑使用 Laravel Forge ,Forge 提供了运行一个带有 Horizon 的现代、强大的 Laravel 应用所需的 PHP7+ 以及其他所有环境。

标签

你可以在 Horizon 中给任务分配 「标签」,包括邮件,事件广播,通知和队列化的事件监听器。事实上,Horizon 会智能并且自动根据任务携带的 Eloquent 模型给大多数任务标记标签,如下任务示例:

  1. <?php
  2. namespace App\Jobs;
  3. use App\Video;
  4. use Illuminate\Bus\Queueable;
  5. use Illuminate\Queue\SerializesModels;
  6. use Illuminate\Queue\InteractsWithQueue;
  7. use Illuminate\Contracts\Queue\ShouldQueue;
  8. use Illuminate\Foundation\Bus\Dispatchable;
  9. class RenderVideo implements ShouldQueue
  10. {
  11. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  12. /**
  13. * The video instance.
  14. *
  15. * @var \App\Video
  16. */
  17. public $video;
  18. /**
  19. * Create a new job instance.
  20. *
  21. * @param \App\Video $video
  22. * @return void
  23. */
  24. public function __construct(Video $video)
  25. {
  26. $this->video = $video;
  27. }
  28. /**
  29. * Execute the job.
  30. *
  31. * @return void
  32. */
  33. public function handle()
  34. {
  35. //
  36. }
  37. }

如果该队列任务携带了一个 id1App\Video 实例,那么它将被标记上 App\Video:1 标签。因为 Horizon 会检查任务属性是否有 Eloquent 模型,如果发现 Eloquent 模型,Horizon将会智能的用该模型的类名和主键为任务标记上标签。

  1. $video = App\Video::find(1);
  2. App\Jobs\RenderVideo::dispatch($video);

自定义标签

如果你想手动的为可队列执行的对象定义标签,你可以给这个类定义一个 tags 方法:

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

通知

Note: 在使用通知之前,你应该为你的项目添加 guzzlehttp/guzzle Composer 包。在使用 Horizon 配置发送短信通知时,你还需要阅读 Nexmo 通知驱动的依赖条件 章节。

如果需要在队列等待时间过长时发起通知,可以在应用的 AppServiceProvider 中调用 Horizon::routeMailNotificationsTo, Horizon::routeSlackNotificationsTo,和 Horizon::routeSmsNotificationsTo 方法 :

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

配置等待时间过长通知的阈值

你可以在 config/horizon.php 文件中配置等待时间过长具体秒数, waits 配置项可以针对每个 链接/队列 配置阈值:

  1. 'waits' => [
  2. 'redis:default' => 60,
  3. ],

Metrics

Horizon 包含一个 metrics 仪表盘,它可以提供任务和队列等待时间和吞吐量信息,为了填充此仪表盘,需要使用应用的 scheduler 每五分钟运行一次 Horizon 的 Artisan 命令 snapshot

  1. /**
  2. * Define the application's command schedule.
  3. *
  4. * @param \Illuminate\Console\Scheduling\Schedule $schedule
  5. * @return void
  6. */
  7. protected function schedule(Schedule $schedule)
  8. {
  9. $schedule->command('horizon:snapshot')->everyFiveMinutes();
  10. }

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。