On the Horizon
Horizon is the Laravel author’s complement to Queue, providing a friendly UI and Supervisor process management
Start the
`php artisan horizon`
Copy the code
Complete structure
The complete structure of Horizon in Redis is explained later.
The source code parsing
This is the source code that was triggered when we launched Horizon, marking 6 areas for analysis
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 ️ ⃣}Copy the code
Six pieces of code analysis
- 1️ one here is the generation of one
gethostname() + Str::random(4)
的Master
Process name. If a process with the same name is created, an error message ~ is returned
-
2️ initialize the MasterSupervisor object
$this->name ($this->name)
If ($this->supervisors) {if ($this->supervisors)
$this->output ($this->output)
The last step is to refresh, refresh high clearly the horizon in this picture: master: gethostname () + Str: : random (4) the process name
$this->connection()->del(‘commands:’.$name);
That’s what it does, go to Redis and delete this key.
-
3️ discount over four LEVELS
Create a resource allocation plan!
The Horizon configuration file contains parameters such as the number of processes, the balance process allocation policy, and so on
This is what is parsed through the ProvisioningPlan class.
🏁 here we parse its corresponding method
ProvisioningPlan::get(MasterSupervisor::name()) This is equivalent to obtaining an object with the specified configuration file and process 'name'.Copy the code
Then,
(new ProvisioningPlan)->deploy($this->option('environment')?? config('horizon.env') ?? config('app.env') );Copy the code
Deploys the configuration of the specified environment. The purpose of this code is to rpush all subsequent instructions to Redis first.
In effect, you perform the following steps to save the parameters to Redis
The code in the figure above does not create this data immediately, but rather ephemerates the associated create instructions to Redis.
To Redis format is, variable on behalf of the name of the machine: ‘commands: master: gethostname () + Str: : random (4)’ : json_encode ($options] [AddSupervisor: : class,)
The $options as shown in figure
Save operations and configurations to
Redis
, after the execution of the time can be found out all relevant data generation corresponding process!🏁 Start confirmation
Execute PHP Artisan Horizon to see the changes in Redis
If it weren’t for the DD (), the data would be consumed immediately!
It is safe to assume that this is the process to be created!
At this point, you must be wondering when Horizon will consume the data in Redis and then generate the corresponding process. This is going to continue to look back!
-
4️ here is nothing good to talk about, after PHP7.1, there is a new signal processing function: pCNTL_async_signals, return or set whether asynchronous signal processing.
-
5️ one signal on terminate is registered here and the function is to close the process. For example, we send this signal when we press Command + C on the Mac Os. Let’s take a quick look at how to shut down all processes. The implementation will be covered later.
-
6️ one is the core part
-
$this – > ensureNoOtherMasterSupervisors (), make sure whether there is a process of the same name, if any, will throw an exception.
-
$this->listenForSignals() registers the signal to be processed
-
$this->persist() ¶
-
$this->loop() to start the process.
$this->processPendingCommands();
This business is going fromRedis
Retrieve the data you just saved
- Start the process.
$this->monitorSupervisors()
The above supervisors have a lot of information, followed by the circular supervisors.
Execute Symfony\Component\Process()->start() to start the supervisors’ sub-processes.
Then execute the command in the commandLine, as follows
- After the startup is complete, print the local process and see the same command as just executed
-
conclusion
The data about the process to be started is saved to the MasterSupervisor object in various ways, and the process is created based on the data in the object.
The Process is terminated, paused, and restarted through the PCNTL extension to implement the listener signal implementation, Process creation through Symfony\Component\Process start() method
Implement.