Horizon
是 Laravel
做者对框架 Queue
的一个补充包,功能强大,使用简单,本章将解析 Horizon
的是如何启动的php
`php artisan horizon`
那么熟悉的命令,一会儿就点亮世界。
复制代码
Horizon 在 Redis 中的完整结构 , 后面解释字段含义。
json
开始进入源码部分了,请坐稳扶好, 这是咱们启动 Horizon 的时候触发的代码,标注了 6 处带分析的地方
bash
public function handle(MasterSupervisorRepository $masters)
{
if ($masters->find(MasterSupervisor::name())) {
return $this->comment('A master supervisor is already running on this machine.');
} 1️⃣
$master = (new MasterSupervisor)->handleOutputUsing(function ($type, $line) {
$this->output->write($line);
}); 2️⃣
ProvisioningPlan::get(MasterSupervisor::name())->deploy(
$this->option('environment') ?? config('horizon.env') ?? config('app.env')
); 3️⃣
$this->info('Horizon started successfully.');
pcntl_async_signals(true); 4️⃣
pcntl_signal(SIGINT, function () use ($master) {
$this->line('Shutting down...');
return $master->terminate();
}); 5️⃣
$master->monitor(); 6️⃣
}
复制代码
gethostname() + Str::random(4)
的 Master
进程名称,若是不幸产生了同名的进程,那么直接返回一个错误提醒~2️⃣初始化 MasterSupervisor
对象php7
$this->name
在第一步就已经生成了静态的名字了app
$this->supervisors
能够看出给了一个集合,一看就是要支持多个进程的样子框架
$this->output
第二步就是让 output
属性能拥有输出到缓冲区的能力dom
最后一步是刷新,刷新高清大图中的 horizon:master:gethostname()+Str::random(4)
这个进程名称异步
关于这个 flush
方法干了啥你们必定很好奇 $this->connection()->del('commands:'.$name);
async
这就是它作的事情,去 Redis
删除这个 key。函数
3️⃣过了四级的我翻译了一下:
建立一个资源分配计划!
这个就是 Horizon
的配置文件,里面的 processes
进程数,balance
进程分配策略等等各项参数
就是经过这个 ProvisioningPlan
类解析的内容。
🏁这里咱们解析一下它对应的方法
ProvisioningPlan::get(MasterSupervisor::name())
这时候至关于获得了一个具备指定配置文件和进程 `Name` 的对象。
复制代码
接着
(new ProvisioningPlan)->deploy(
$this->option('environment') ?? config('horizon.env') ?? config('app.env')
);
复制代码
部署指定环境的配置,这段代码目的是将全部后面要执行的指令先 rpush
到 Redis
中。
实际就是执行下图方法,将参数存到 Redis
上图中的代码不会当即建立这些数据,而是暂存了相关建立指令到 Redis
。
存到Redis
的格式是,变量表明本机名称: 'commands:master:gethostname()+Str::random(4)': json_encode([AddSupervisor::class,$options])
$options 如图
这样理解,就是把操做和配置存到 Redis
,后面要执行的时候就能够查出全部相关的数据生成对应的进程!
🏁动手确认
执行 php artisan horizon
去看看 Redis
中的变化
要不是这个 dd()
这个数据立马就被消费了!
咱们此时能够大胆猜测下图中就是后续要建立的进程!
这时候你们确定有疑问了,接下来 Horizon
将会在何时消费掉 Redis
中的数据,而后生成对应的 进程呢。这个就要继续日后看了!
4️⃣这里没什么好讲的,在php7.1以后,有了新的信号处理函数:pcntl_async_signals,返回或设置是否异步信号处理。
5️⃣这里注册一个 terminate
的信号,功能是关闭进程。好比咱们在 Mac Os
按 Command + C
的时候就是发送这个信号。咱们先大概看一下,是如何关闭全部进程的,具体实现放到后面的篇幅讲。
6️⃣好了,到了本章最核心的部分了,先看核心方法
$this->ensureNoOtherMasterSupervisors()
,确保是否存在相同名字的进程,若是有,就抛出异常。
$this->listenForSignals()
,注册将要处理的信号
$this->persist()
将 Redis
中 Commands
下的 key
更新到 Master
下面。
接着执行 $this->loop()
, 启动进程。
这里咱们关注 $this->monitorSupervisors()
调用。
这里的类是 Laravel\Horizon\SupervisorProcess
,别问我怎么知道的!dd()
出来看到的~~,其实要分析就要回到前面去看,初始化那部分了。
最后
这里就是控制启动进程相关的代码了,其实 $this->process
也是使用了 Symfony\Component\Process
这个老大哥包里面的功能,毕竟它已经完整的实现了进程管理。英文好的铁汁自行解读其中内容。
打印
经历过上面的阶段,咱们打印一下本机的进程
关于前面那个管理实例的初始化部分有些略过,
你们能够这样理解,就是经过各类方式将要启动的进程相关数据保存到 MasterSupervisor
对象中,在最后根据对象中的数据建立进程。
本章总算结束了,php artisan horizon
如此而已。