2018-08-06Laravel官方扩展包——队列系统解决方案:Laravel Horizon

简介

Horizon 为 Laravel 提供了基于 Redis 的、拥有美观后台的、代码驱动配置的队列系统。Horizon 让我们可以轻松监控队列系统的关键指标,例如任务吞吐量、运行时间和失败任务等。

所有的队列进程配置都存放在一个单独的简单配置文件中,这样的话配置文件就可以存放到源码控制以便团队所有成员的协作。

安装

注:由于 Horizon 使用了异步进程信号,所以 PHP 7.1+ 以上版本才可以使用。

composer安装Horizon命令:

composer require laravel/horizon

安装完成后,使用 Artisan 命令 vendor:publish 发布前端资源:

php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
配置

发布好前端资源后,主配置文件就会出现在 config/horizon.php。在这个配置文件中,你可以配置队列进程选项以及每个包含目的描述的配置项,使用 Horizon 前可浏览下这个配置文件。

balance 配置项

Horizon 提供了三种负载均衡策略以供选择:simple、auto 和 false,simple 是默认策略,在进程之间平均分配进入任务:

'balance' => 'simple',

auto 策略基于队列当前负载调整每个队列的工作进程数量。例如,如果 notifications 队列有 1000 个等待执行的任务而 render 队列是空的,那么 Horizon 将会为 notifications 队列分配更多的工作进程直到队列为空。

如果把 balance 选项设置为 false,就会使用默认的 Laravel 行为,也就是按照配置文件中的排列顺序处理队列。

后台认证

我们可以通过 /horizon 访问 Horizon 后台:

image.png

默认情况下,你只能在 local环境下访问这个后台。如果想要为后台定义更多的特定访问策略,需要使用 Horizon:auth 方法。auth 方法接收一个返回truefalse 的回调,从而决定用户是否可以访问 Horizon 后台。通常,我们会在 AppServiceProviderboot 方法中调用 Horizon:auth

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Horizon\Horizon;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //用户是否可以访问 Horizon 后台
        Horizon::auth(function ($request) {
            // return true / false;
        });
    }
}
运行 Horizon

如果你已经在配置文件 config/horizon.php 中配置过工作进程,就可以使用 Artisan 命令 horizon 来启动 Horizon,该命令会启动所有配置的工作进程:

php artisan horizon

使用 Artisan 命令 horizon:pausehorizon:continue 来暂停或继续处理队列任务:

php artisan horizon:pause

php artisan horizon:continue

还可以使用 Artisan 命令 horizon:terminate 来优雅地终止 Horizon 主进程 —— Horizon 会在所有当前正在执行的任务全部完成后退出:

php artisan horizon:terminate
部署 Horizon

如果要将 Horizon 部署到线上服务器,需要配置一个进程监控来监控 php artisan horizon 命令的运行并在异常退出的情况下重启该进程。部署新代码到服务器的时候,需要终止 Horizon 主进程以便通过配置的进程监控以最新代码重启进程。如上所述,我们可以通过 Artisan 命令 horizon:terminate 优雅地终止 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

注:也可以考虑使用 Laravel ForgeForge 提供了 PHP 7+ 版本的服务器,并且拥有运行最新版 Laravel 应用所需的所有软件工具集。

标签

Horizon 允许分配"标签"到任务,包括邮件、事件广播、通知以及队列事件监听器等。实际上,Horizon 会基于附加到任务的 Eloquent 模型为大部分任务以智能的方式自动打上标签。例如,我们来看看下面这个例子:

<?php

namespace App\Jobs;

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

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

    /**
     * The video instance.
     *
     * @var \App\Video
     */
    public $video;

    /**
     * Create a new job instance.
     *
     * @param  \App\Video  $video
     * @return void
     */
    public function __construct(Video $video)
    {
        $this->video = $video;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

如果任务被推送到队列时附带了一个 id1App\Video 实例,它将会自动打上 App\Video:1 的标签,这是因为 Horizon 会检查队列任务属性中的 Eloquent 模型,如果 Eloquent 模型被找到,Horizon 就会使用模型类名和主键为任务智能地打上标签:

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

App\Jobs\RenderVideo::dispatch($video);
手动打标签

如果你想要手动定义某个队列对象的标签,可以在该类中定义一个 tags 方法:

class RenderVideo implements ShouldQueue
{
    /**
     * Get the tags that should be assigned to the job.
     *
     * @return array
     */
    public function tags()
    {
        return ['render', 'video:'.$this->video->id];
    }
}
通知

注:在使用通知之前,需要通过 Composer 安装 guzzlehttp/guzzle 依赖。在配置 Horizon 发送短信通知前,还要回顾下 Nexmo 通知驱动的预备知识

如果你想要在某个队列任务等待很长时间后被通知,可以使用 Horizon::routeMailNotificationsToHorizon::routeSlackNotificationsTo 以及 Horizon::routeSmsNotificationsTo 方法。你可以在 AppServiceProvider 中调用这些方法:

Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
Horizon::routeSmsNotificationsTo('15556667777');
配置通知等待时间下限

你可以在配置文件 config/horizon.php 中通过修改 waits 配置项来配置每个连接/队列上的等待时间下限(秒):

'waits' => [
    'redis:default' => 60,
],
监控

Horizon 提供了一个监控后台查看任务和队列的等待时间和吞吐量信息,为了获取实时信息,可以配置 HorizonArtisan 命令 snapshot 通过应用的调度器每五分钟运行一次:

/**
 * Define the application's command schedule.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('horizon:snapshot')->everyFiveMinutes();
}

出处

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • Laravel 学习交流 QQ 群:375462817 本文档前言Laravel 文档写的很好,只是新手看起来会有...
    Leonzai阅读 7,648评论 2 12
  • 原文链接 必备品 文档:Documentation API:API Reference 视频:Laracasts ...
    layjoy阅读 8,597评论 0 121
  • 队列 简介 laravel 的队列服务对各种不同的后台队列服务提供了统一的 API。队列允许你延迟执行消耗时间的任...
    Dearmadman阅读 20,731评论 7 26
  • 有多久没有读完一本书了。记得小时候爸爸每年都会带我去书市,买一大堆书回来,还会买些好吃的,到家后和妈妈一起吃顿大餐...
    靜听心曲阅读 189评论 0 0
  • 睡到自然醒,舒服至极。 游玩,聊天,学习。 好像感觉没有那么振奋去过这一天,很自在很舒适。没有觉得必须去做,自然想...
    远山近水_阅读 79评论 0 0