Ich habe kürzlich ein Laravel Queue-System eingerichtet. Die Grundlagen sind, dass ein Cronjob einen Befehl aufruft, der einer Warteschlange Jobs hinzufügt, und einen zweiten Befehl aufruft, der eine E-Mail sendet.
Das System funktioniert, wenn ich in meinen Server ssh und die PHP Artisan Queue ausführe: Listen, aber wenn ich mein Terminal schließe, wird der Listener heruntergefahren und die Jobs stapeln sich und sitzen in der Warteschlange, bis ich wieder ssh bin und Listen erneut ausführen.
Was ist der beste Weg, um mein Warteschlangensystem im Hintergrund laufen zu lassen, ohne dass meine Verbindung über ssh offen bleiben muss?
Ich habe versucht zu rennen php artisan queue:work --daemon
, es , und es hat die Jobs in der Warteschlange abgeschlossen, aber als ich mein Terminal geschlossen habe, wurden die Verbindung und der Hintergrundprozess geschlossen.
nohup php artisan queue:work --daemon > storage/logs/laravel.log &
arbeitete ich für mich. Hinweis: Wenn Sie den Nohup-Daemon beenden möchten, müssen Sie zuerst seine PID ermitteln, indem Sie so etwas wie ausführenps -ef |grep artisan
. Dann können Siekill [pid]
stackoverflow.com/q/17385794/470749Sie sollten Linux Supervisor verwenden
Die Installation ist einfach und unter Ubuntu kann ich sie mit folgendem Befehl installieren:
Supervisor-Konfigurationsdateien befinden sich im Verzeichnis /etc/supervisor/conf.d.
[program:email-queue] process_name=%(program_name)s_%(process_num)02d command=php /var/www/laravel-example/artisan queue:work redis --queue=emailqueue --sleep=3 --tries=3 autostart=true autorestart=true user=forge numprocs=2 redirect_stderr=true stdout_logfile=/var/www/laravel-example//storage/logs/supervisord.log
Für jeden Prozess sollten Sie eine neue Prozesskonfigurationsdatei erstellen. Mit dieser Konfiguration wiederholt der Listener jeden Job dreimal. Außerdem wird Supervisor den Listener neu starten, wenn dies fehlschlägt oder wenn das System neu gestartet wird.
quelle
Der Befehl
Wenn dies korrekt ist, kann der Prozess nach dem Schließen der SSH-Verbindung fortgesetzt werden. Dies ist jedoch nur eine kurzfristige Lösung. Sobald Ihr Server neu gestartet wurde oder ein Problem dazu führt, dass der Prozess gestoppt wird, müssen Sie zurückgehen und den Befehl erneut ausführen. Wann das passiert, weiß man nie. Es könnte an einem Freitagabend passieren, daher ist es besser, eine langfristige Lösung zu implementieren.
Am Ende bin ich auf Supervisord umgestiegen. Dies kann unter Ubuntu so einfach wie möglich installiert werden
Für AWS-AMI- oder RedHat-Benutzer können Sie die Anweisungen befolgen, die ich in dieser Frage beschrieben habe:
Einrichten von Supervisord auf einem AWS AMI Linux Server
quelle
Von https://gist.github.com/ivanvermeyen/b72061c5d70c61e86875
<?php namespace App\Console\Commands; use Illuminate\Console\Command; class EnsureQueueListenerIsRunning extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'queue:checkup'; /** * The console command description. * * @var string */ protected $description = 'Ensure that the queue listener is running.'; /** * Create a new command instance. */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return void */ public function handle() { if ( ! $this->isQueueListenerRunning()) { $this->comment('Queue listener is being started.'); $pid = $this->startQueueListener(); $this->saveQueueListenerPID($pid); } $this->comment('Queue listener is running.'); } /** * Check if the queue listener is running. * * @return bool */ private function isQueueListenerRunning() { if ( ! $pid = $this->getLastQueueListenerPID()) { return false; } $process = exec("ps -p $pid -opid=,cmd="); //$processIsQueueListener = str_contains($process, 'queue:listen'); // 5.1 $processIsQueueListener = ! empty($process); // 5.6 - see comments return $processIsQueueListener; } /** * Get any existing queue listener PID. * * @return bool|string */ private function getLastQueueListenerPID() { if ( ! file_exists(__DIR__ . '/queue.pid')) { return false; } return file_get_contents(__DIR__ . '/queue.pid'); } /** * Save the queue listener PID to a file. * * @param $pid * * @return void */ private function saveQueueListenerPID($pid) { file_put_contents(__DIR__ . '/queue.pid', $pid); } /** * Start the queue listener. * * @return int */ private function startQueueListener() { //$command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.1 $command = 'php-cli ' . base_path() . '/artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments $pid = exec($command); return $pid; } }
quelle
queue:work
bedeutet, dass keine Codeänderungen abgehört wurden oder zumindest der Prozess manuell neu gestartet werden muss. aber im Code habe ich keinen Neustart gesehen .. irgendeine Idee?1)
sudo apt install supervisor
oder2)
cd /etc/supervisor/conf.d
3) Erstellen Sie eine neue Datei im InnerenDateiinhalt
[program:email-queue] process_name=%(program_name)s_%(process_num)02d command=php /var/www/html/laravelproject/artisan queue:work autostart=true autorestart=true user=root numprocs=2 redirect_stderr=true stdout_logfile=/var/www/html/laravelproject/storage/logs/supervisord.log
4)
sudo supervisorctl reread
Wenn Sie diesen Befehl ausführen, erhalten Sie den Ausgabewarteschlangen-Worker: verfügbar
5)
sudo supervisorctl update
Wenn Sie diesen Befehl ausführen, erhalten Sie den Ausgabewarteschlangen-Worker: Prozessgruppe hinzugefügt
anderer Befehl
1)
sudo supervisorctl reload
Wenn Sie diesen Befehl ausführen, erhalten Sie die Ausgabe. Neustart Supervisord
2)
sudo service supervisor restart
quelle
Schritt 1: Gehen Sie zum Verzeichnis /etc/supervisor/conf.d
Schritt 2: Erstellen Sie eine Worker-Datei laravel-worker.conf , die die Warteschlange abhört
* Hinweis: Angenommen, Ihre Laravel-App befindet sich im
/var/www/html
Verzeichnisproject folder is : /var/www/html/LaravelApp
Schritt 3: Fügen Sie den folgenden Code in die laravel-worker.conf ein und speichern Sie die Datei
[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /var/www/html/LaravelApp/artisan queue:listen redis --queue=default --sleep=3 --tries=3 autostart=true autorestart=true user=root numprocs=8 redirect_stderr=true stdout_logfile= /var/www/html/LaravelApp/storage/logs/worker.log
* Hinweis: Hier wird davon ausgegangen, dass Sie Redis verwenden für die Warteschlangenverbindung verwenden
in der .env-Datei
QUEUE_CONNECTION=redis
command=php /var/www/html/LaravelApp/artisan queue:listen redis
Wenn Sie eine andere Verbindung verwenden, lautet die allgemeine Syntax wie folgt:
[connection_name] kann eine beliebige sein sync , Datenbank , beanstalkd , sqs , redis
Schritt 4: Erstellen Sie eine Worker-Datei laravel-sched.conf , die den
artisan schedule:run
Befehl alle 1 Minute (60 Sekunden) ausführt (* Sie können ihn gemäß Ihren Anforderungen ändern).[program:laravel-schedule] process_name=%(program_name)s_%(process_num)02d command=/bin/bash -c 'while true; do date && php /var/www/html/LaravelApp/artisan schedule:run; sleep 60; done' autostart=true autorestart=true numprocs=1 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0
Schritt 5: Starten von Supervisor: Führen Sie die folgenden Befehle aus
Zusätzliche nützliche Informationen:
sudo supervisorctl stop all
sudo supervisorctl restart all
nützliche Links:
https://laravel.com/docs/5.8/queues#running-the-queue-worker
http://supervisord.org/index.html
quelle
Für diejenigen, die NodeJS bereits in ihren Produktionsumgebungen ausführen . Ich verwende PM2, um App-Prozesse zu verwalten.
# install npm install -g pm2 # in project dir with your CI or dev setup tool # --name gives task a name so that you can later manage it # -- delimits arguments that get passed to the script pm2 start artisan --interpreter php --name queue-worker -- queue:work --daemon
Ich verwende Vagrant in der Entwicklung und Einrichtung von NodeJS und diesen Prozess nur mit Inline-Vagrant-Skripten.
Wenn Sie PM2 in der Entwicklung verwenden, können Sie einen der vielen Beobachter verwenden, um den Neustart zu verwalten. Einfach ausführen,
pm2 restart queue-worker
wenn Sie eine Änderung abholen. In der Produktion empfehle ich diesen Ansatz nicht, sondern entscheide mich für ein Build-Tool, das diesem Prozess folgen kann.# 1. stop pm task to ensure that no unexpected behaviour occurs during build pm2 stop queue-worker # 2. do your build tasks ... # 3. restart queue so that it loads the new code pm2 restart queue-worker
quelle
Mit pm2
Ich hatte JS-Skript mit pm2 ausgeführt (Advanced, Produktionsprozessmanager für Node.js). war das einzige, das ich . Aber jetzt, da ich noch einen Prozess habe, um weiterzulaufen.
Ich habe erstellt
process.yml
, um beide mit einem einzigen Befehl auszuführen. Überprüfen Sie, ob der erste ausgeführt wirdphp artisan queue: listen
# process.yml at /var/www/ which is root dir of the project apps: # Run php artisan queue:listen to execute queue job - script : 'artisan' name : 'artisan-queue-listen' cwd : '/var/www/' args : 'queue:listen' # or queue:work interpreter : 'php' # same way add any other script if any.
Führen Sie jetzt aus:
Überprüfen Sie weitere Optionen und Funktionen von pm2
quelle
Da dies eine Laravel-spezifische Frage war, dachte ich, ich würde eine Lravel-spezifische Antwort vorschlagen. Da Sie auf diesem Server bereits Cronjobs verwenden, würde ich empfehlen, den Shell-Befehl als wiederkehrenden Cronjob einzurichten, um immer zu überprüfen, ob der Worker ausgeführt wird. Sie können entweder den Shell-Befehl so einrichten, dass er nativ über cron auf Ihrem Server ausgeführt wird, oder Sie können den Laravel-Konsolenkernel verwenden, um den Befehl zu verwalten und Logik hinzuzufügen, z. B. zu überprüfen, ob bereits ein Worker ausgeführt wird, und wenn nicht, fortzufahren und starten Sie es wieder.
Je nachdem, wie oft Sie Ihren Befehl ausführen müssen, können Sie dies so selten wie einmal pro Woche oder sogar einmal pro Minute tun. Auf diese Weise können Sie sicherstellen, dass Ihre Mitarbeiter kontinuierlich ausgeführt werden, ohne dass Sie Ihrem Server, z. B. Supervisor, zusätzlichen Aufwand hinzufügen müssen. Das Erteilen von Berechtigungen für ein Paket eines Drittanbieters wie Supervisor ist in Ordnung, wenn Sie ihm vertrauen. Wenn Sie jedoch vermeiden können, sich darauf verlassen zu müssen, sollten Sie stattdessen diesen Ansatz in Betracht ziehen.
Ein Beispiel dafür, wie Sie das tun, was Sie wollen, wäre ein Cronjob, der jede Stunde ausgeführt wird. In einem benutzerdefinierten Laravel-Konsolenbefehl wird Folgendes in sequentieller Reihenfolge ausgeführt:
\ Artisan :: call ('Warteschlange: Neustart');
\ Artisan :: call ('queue: work --daemon');
Beachten Sie, dass dies für ältere Versionen von Laravel (bis zu 5.3) gilt, ich jedoch nicht auf neueren Versionen getestet habe.
quelle
Der beste Weg ist PM2 (Advanced, Production Process Manager für Node.js), mit dem Sie Ihre Warteschlangen überwachen und deren Protokolle anzeigen können.
Führen Sie mit dem folgenden Befehl in Ihrem Projektverzeichnis den Warteschlangenarbeiter aus:
quelle
Was ist, wenn Sie das Hören innerhalb eines Bildschirms starten? Siehe hier: http://aperiodic.net/screen/quick_reference Selbst wenn Sie sich abmelden, ist der Bildschirm weiterhin aktiv und läuft. Ich bin mir nicht sicher, warum die Dämonisierung nicht funktioniert.
quelle
Sie können das Überwachungswerkzeug verwenden. Es ist sehr klein und nützlich für jede Art von Prozessmanagement und -überwachung.
Nachdem Sie das Binärpaket über diesen Link heruntergeladen haben , können Sie es in einen Ordner auf Ihrem System extrahieren und anschließend zwei Dateien aus dem Paket auf Ihr System kopieren, um es zu installieren:
Bearbeiten Sie nun die
/etc/monitrc
Basis nach Ihren Wünschen ( Referenzdokument ). Erstellen Sie dann eine Init-Steuerdatei , um die Überwachung beim Start zu aktivieren. Starten Sie jetzt die Überwachung wie folgt:quelle
Für CentOS7
Erstellen Sie dann eine Datei in /etc/supervisord.d/filename.ini mit Inhalt
[program:laravel-worker] command=/usr/bin/php /home/appuser/public_html/artisan queue:listen process_name=%(program_name)s_%(process_num)02d numprocs=5 priority=999 autostart=true autorestart=true startsecs=1 startretries=3 user=appuser redirect_stderr=true stdout_logfile=/path/logpath/artisan.log
Starten Sie dann den Supervisord-Dienst mit
Aktivieren Sie den Supervisord-Dienst, um ihn beim Booten mit auszuführen
Überprüfen Sie, ob der Dienst mit ausgeführt wird
Sie sollten sehen, dass der Prozess ausgeführt wird, wenn er ordnungsgemäß eingerichtet wurde. Ähnlich wie bei der folgenden Ausgabe.
[root@server ~]# ps aux | grep artisan appuser 17444 0.1 0.8 378656 31068 ? S 12:43 0:05 /usr/bin/php /home/appuser/public_html/artisan queue:listen
quelle
Für Systeme mit systemd als Init-Dienst können Sie den folgenden Dienst verwenden und ihn an Ihr Projekt anpassen (erstellen Sie ihn unter /etc/systemd/system/queue-handler.service):
[Unit] Description = Queue Handler - Project After = network-online.target, mysql.service [Service] User = www-data Type = simple WorkingDirectory=/var/www/project ExecStart = /usr/bin/php /var/www/project/artisan queue:work --tries=3 Restart = on-failure RestartSec=5s RestartPreventExitStatus = 255 [Install] WantedBy = multi-user.target
Laden Sie die Konfigurationen neu und aktivieren Sie sie beim Booten:
$ systemctl enable queue-handler.service $ systemctl daemon-reload
quelle
Sie können auch Docker-Container verwenden.
Auschecken:
quelle
Ich habe das Ergebnis ohne Service-Monitor oder Software von Drittanbietern erzielt. Die Lösung funktioniert gut, aber ich bin mir nicht sicher, ob es der beste Weg ist.
Lösung
Führen Sie den Befehl cli in Ihrer Funktion einfach wie folgt aus.
use Illuminate\Console\Command; public function callQueue() { $restart = 'php-cli ' . base_path() . '/artisan queue:restart > /dev/null & echo $!'; $work = 'php-cli ' . base_path() . '/artisan queue:work --timeout=0 --sleep=5 --tries=3 > /dev/null & echo $!'; exec($restart); exec($work); } $job = (new jobName())->delay(Carbon::now()->addSeconds(5)); dispatch($job);
Grund
Der Grund, warum ich diese beiden Befehle verwendet habe, ist, dass der Befehl zum
$restart
Verhindern von Speicherproblemen gemäß einem Kommentar in dieser Antwort und der zugeordnete Befehl$work
sicherstellen, dass der Befehl vor dem Job erfolgreich ausgeführt wird.quelle
Ich habe einfach verwendet,
php artisan queue:work --tries=3 &
was den Prozess im Hintergrund laufen lässt. Aber manchmal hört es auf. Ich weiß nicht, warum das passiertBearbeiten
Ich habe dieses Problem mithilfe des Supervisors gelöst. Fügen Sie ein Supervisor-Skript ein, das dieses PHP-Skript ausführt und das jedes Mal ausgeführt wird, wenn der Server ausgeführt wird
quelle