In diesem Beitrag erfahren Sie, wie Sie supervisord verwenden, um die Ausführung eines Symfony-Befehls zu verwalten. Grundsätzlich erlaubt uns der Vorgesetzte:
Manchmal greifen wir auf die Unix-Crontab zurück, um die Ausführung von Prozessen zu automatisieren. Dies mag in den meisten Fällen funktionieren, aber es kann Situationen geben, in denen es Probleme verursachen kann.
Stellen wir uns vor, wir hätten eine Datenbanktabelle, die die Benachrichtigungen der Benutzer protokolliert. Die Tabelle speichert die folgenden Informationen:
Andererseits haben wir einen Befehl codiert, dessen Ausführung den nächsten Schritten folgt:
Wir haben diesen Befehl in der Linux-Crontab so eingestellt, dass er von Zeit zu Zeit ausgeführt wird (1 Minute, 2 Minuten usw.). So weit so gut.
Stellen wir uns nun vor, dass der aktuelle Prozess 500 Benachrichtigungen abgefragt hat und wenn er 400 gesendet hat, startet ein neuer Prozess. Das bedeutet, dass der neue Prozess die 100 Benachrichtigungen abfragt, die vom letzten Prozess noch nicht aktualisiert wurden, plus die neuen:
Dies kann dazu führen, dass diese 100 Benachrichtigungen zweimal gesendet werden, da beide Prozesse sie abgefragt haben.
Als Lösung können wir auf den Einsatz eines Supervisors zurückgreifen. Es hält unseren Prozess am Laufen und startet ihn bei Bedarf neu. Auf diese Weise behalten wir nur einen Prozess bei und vermeiden Überschneidungen. Lassen Sie uns analysieren, wie der Befehl aussehen sollte:
#[AsCommand( name: 'app:notification' )] class NotificationCommand extends Command { private bool $forceFinish = false; protected function configure(): void { $this ->addOption('time-limit', null, InputOption::VALUE_OPTIONAL, 'Max time alive in seconds') ->addOption('time-between-calls', null, InputOption::VALUE_OPTIONAL, 'Time between every loop call') ; } protected function execute(InputInterface $input, OutputInterface $output): int { $this->forceFinish = false; pcntl_signal(SIGTERM, [$this, 'signalHandler']); pcntl_signal(SIGINT, [$this, 'signalHandler']); $timeLimit = $input->getOption('time-limit'); $timeBetweenCalls = $input->getOption('time-between-calls'); $dtMax = (new \DateTimeImmutable())->add(\DateInterval::createFromDateString("+ {$timeLimit} seconds")); do{ // Here we should execute a service to query and send notifications // ...... sleep($timeBetweenCalls); $dtCurrent = new \DateTimeImmutable(); }while($dtCurrent < $dtMax && !$this->forceFinish); return Command::SUCCESS; } public function signalHandler(int $signalNumber): void { echo 'Signal catch: ' . $signalNumber . PHP_EOL; match ($signalNumber) { SIGTERM, SIGINT => $this->forceFinish = true, default => null }; } }
Lassen Sie uns den Befehl Schritt für Schritt erklären:
Die Methode configure deklariert Eingabeoptionen:
Die Methode execute verhält sich wie folgt:
Die Funktion signalHandler fängt die Unix-Signale SIGTERM und SIGINT ab. SIGINT ist das Signal, das gesendet wird, wenn wir Strg+C drücken, und SIGTERM ist das Standardsignal, wenn wir den Kill-Befehl verwenden. Wenn die Funktion signalHandler sie erkennt, setzt sie die Variable forceFinish auf „true“, sodass der Befehl nach Abschluss der aktuellen Schleife beendet wird, da die Variable forceFinish vorhanden ist nicht mehr falsch. Dadurch können Benutzer den Vorgang beenden, ohne warten zu müssen, bis das maximale Datum abgelaufen ist.
Bisher haben wir den Befehl erstellt. Jetzt ist es an der Zeit, den Supervisor so einzurichten, dass er damit umgehen kann. Bevor wir mit der Konfiguration beginnen, müssen wir Supervisor installieren. Sie können dies tun, indem Sie den folgenden Befehl ausführen:
sudo apt update && sudo apt install supervisor
Nach der Installation können Sie sicherstellen, dass Supervisor ausgeführt wird, indem Sie den nächsten Befehl ausführen:
sudo systemctl status supervisor
Supervisor-Konfigurationsdateien werden im folgenden Ordner abgelegt: /etc/supervisor/conf.d. Erstellen wir eine Datei mit dem Namen notif.conf und fügen den folgenden Inhalt ein:
command=php <your_project_folder>/bin/console app:notifications --time-limit=120 --time-between-calls=10 user=<your_user> numprocs=1 autostart=true autorestart=true process_name=%(program_name)s_%(process_num)02d
Lassen Sie uns jeden Schlüssel erklären:
Mit dieser Konfiguration wird der Befehl app:notifications maximal 120 Sekunden lang ausgeführt und nach jeder Schleife 10 Sekunden lang in den Ruhezustand versetzt. Nach Ablauf von 120 Sekunden oder Zwischenspeichern eines Unix-Signals verlässt der Befehl die Schleife und wird beendet. Dann wird der Vorgesetzte es erneut starten.
Wir haben gelernt, wie man Supervisor verwendet, um einen Befehl am Laufen zu halten, ohne die Crontab verwenden zu müssen. Dies kann nützlich sein, wenn sich die von der Crontab gestarteten Prozesse überschneiden und zu Datenbeschädigungen führen können.
Im letzten Buch, das ich geschrieben habe, zeige ich, wie man Supervisor verwendet, um die Symfony Messenger-Worker am Laufen zu halten. Wenn Sie mehr wissen möchten, finden Sie das Buch hier: Building an Operation-Oriented Api using PHP and the Symfony Framework: A Step-by-Step Guide
Das obige ist der detaillierte Inhalt vonVerwenden von Supervisor zur Abwicklung der Ausführung eines Symfony-Befehls. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!