Warteschlange
Warteschlange
- Einführung
- Erstellung Aufgabe erstellen
- Verteilungsaufgabe
- Warteschlange Schließung
- Warteschlangenhandler ausführen
- Supervisor Konfiguration
- Behandlung fehlgeschlagener Aufgaben
- Questereignisse
Einführung
{Tipp} Laravel bietet jetzt Horizon an, ein schönes Dashboard und Konfigurationssystem für Ihre Redis-Warteschlangen. Weitere Informationen finden Sie in der vollständigen Horizon-Dokumentation.
Laravel Queue bietet eine einheitliche API für verschiedene Backend-Warteschlangendienste wie Beanstalk, Amazon SQS, Redis und sogar andere Warteschlangen, die auf relationalen Datenbanken basieren. Der Zweck der Warteschlange besteht darin, die Verarbeitung zeitaufwändiger Aufgaben wie das Versenden von E-Mails zu verzögern und so die Zeit für Webanfragen und -antworten erheblich zu verkürzen.
Warteschlangenkonfigurationsdateien werden in config/queue.php
-Dateien gespeichert. Die Konfiguration für jeden Warteschlangentreiber finden Sie in dieser Datei, einschließlich Datenbank, Beanstalkd, Amazon SQS, Redis und Synchronisierungstreiber (lokale Verwendung). Es enthält außerdem einen null
Warteschlangentreiber für Aufgaben, die die Warteschlange verlassen.
Verbindung vs. Warteschlange
Bevor Sie mit der Verwendung der Laravel-Warteschlange beginnen, ist es wichtig, den Unterschied zwischen „Verbindung“ und „Warteschlange“ zu verstehen. In Ihrer config/queue.php
-Konfigurationsdatei gibt es eine connections
-Konfigurationsoption. Diese Option definiert eine eindeutige Verbindung zu einem Backend-Dienst wie Amazon SQS, Beanstalk oder Redis. In beiden Fällen kann es für eine bestimmte Verbindung mehrere „Warteschlangen“ geben, und „Warteschlangen“ können als unterschiedliche Stapel oder eine große Anzahl von Aufgaben in der Warteschlange betrachtet werden.
Es ist wichtig zu beachten, dass das Konfigurationsbeispiel für jede Verbindung in der queue
-Konfigurationsdatei ein queue
-Attribut enthält. Dies ist die Standardwarteschlangenaufgabe, die an diese Warteschlange verteilt wird, wenn sie an die angegebene Verbindung gesendet wird. Mit anderen Worten: Wenn Sie beim Verteilen einer Aufgabe keine Warteschlange explizit definieren, wird diese in die Warteschlange gestellt, die durch das Attribut queue
in der Verbindungskonfiguration definiert ist:
// 这个任务将被分发到默认队列... Job::dispatch(); // 这个任务将被发送到「emails」队列... Job::dispatch()->onQueue('emails');
Einige Anwendungen müssen möglicherweise nicht gestellt werden Die Aufgabe wird an verschiedene Warteschlangen gesendet. Senden Sie sie einfach an eine einfache Warteschlange. Das Verschieben von Aufgaben in verschiedene Warteschlangen ist jedoch immer noch sehr nützlich, da Sie mit dem Laravel-Warteschlangenhandler die Priorität der Warteschlange definieren können, sodass Sie verschiedenen Warteschlangen unterschiedliche Prioritäten zuweisen oder verschiedene Verarbeitungsmethoden für verschiedene Aufgaben unterscheiden können. Wenn Sie beispielsweise eine Aufgabe an high
verschieben In der Warteschlange können Sie den Warteschlangenprozessor diese Aufgaben priorisieren lassen:
php artisan queue:work --queue=high,default
Notwendige Treibereinstellungen
Datenbank
Zur Verwendungdatabase
Warteschlangentreiber, Sie benötigen eine Datentabelle zum Speichern von Aufgaben. Führen Sie den Befehl queue:table
Artisan aus, um die Migrationsdatei für diese Tabelle zu erstellen. Wenn die Migrationsdatei erstellt ist, können Sie den Befehl migrate
zum Migrieren verwenden:
php artisan queue:table php artisan migrate
Redis
Um den Warteschlangentreiber redis
zu verwenden, müssen Sie Sie müssen config/database.php
die Redis-Datenbankverbindung in der Konfigurationsdatei konfigurieren.
Redis-Cluster
Wenn Ihr Redis-Warteschlangentreiber Redis-Cluster verwendet, muss Ihr Warteschlangenname ein Schlüssel-Hash-Tag enthalten. Dadurch soll sichergestellt werden, dass alle Redis-Schlüssel für eine Warteschlange im selben Hash platziert werden.
'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => '{default}', 'retry_after' => 90, ],
Blockieren
Bei Verwendung einer Redis-Warteschlange können Sie mit dem Konfigurationselement block_for
festlegen, dass der Treiber die Aufgabe zurück in die Redis-Datenbank stellen soll und Prozessor Wie lange vor der Abfrage blockiert werden soll.
Es ist viel effizienter, diesen Wert basierend auf Ihrer Warteschlangenlast anzupassen, als die Redis-Datenbank nach neuen Aufgaben abzufragen. Sie könnten diesen Wert beispielsweise auf 5
setzen, um anzugeben, dass der Treiber 5 Sekunden lang blockieren soll, während er darauf wartet, dass eine Aufgabe verfügbar wird.
'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => 'default', 'retry_after' => 90, 'block_for' => 5, ],
Andere Abhängigkeitserweiterungspakete für Warteschlangentreiber
Bevor Sie den Warteschlangendienst in der Liste verwenden, müssen die folgenden Abhängigkeitserweiterungspakete installiert werden:
- Amazon SQS:
aws/aws-sdk-php ~3.0
- Beanstalkd:
pda/pheanstalk ~4.0
- Redis:
predis/predis ~1.0
Aufgabe erstellen
Aufgabenklassen generieren
In Ihrer Anwendung werden die Aufgabenklassen der Warteschlange standardmäßig platziert app/Jobs
Verzeichnis. Wenn dieses Verzeichnis nicht existiert, wird es automatisch erstellt, wenn Sie den Befehl make:job
Artisan ausführen. Sie können den folgenden Artisan-Befehl verwenden, um eine neue Warteschlangenaufgabe zu generieren:
php artisan make:job ProcessPodcast
Die generierte Klasse implementiert die IlluminateContractsQueueShouldQueue
-Schnittstelle, was bedeutet, dass die Aufgabe in die Warteschlange verschoben und nicht synchron ausgeführt wird.
Aufgabenklassenstruktur
Die Struktur der Aufgabenklasse ist im Allgemeinen sehr einfach, sie enthält nur a Warteschlange zum Aufrufen der handle
-Methode dieser Aufgabe. Schauen wir uns eine Beispiel-Aufgabenklasse an. Nehmen wir in diesem Beispiel an, dass wir einen Podcast-Veröffentlichungsdienst verwalten und hochgeladene Podcast-Dateien vor der Veröffentlichung verarbeiten müssen:
<?php namespace App\Jobs; use App\Podcast; use App\AudioProcessor; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class ProcessPodcast implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $podcast; /** * 创建一个新的任务实例。 * * @param Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; } /** * 运行任务。 * * @param AudioProcessor $processor * @return void */ public function handle(AudioProcessor $processor) { // Process uploaded podcast... } }
Beachten Sie, dass wir in diesem Beispiel ein Eloquent-Modell direkt im Konstruktor der Task-Klasse übergeben. Da wir in der Task-Klasse auf das Merkmal SerializesModels
verwiesen haben, kann das Eloquent-Modell bei der Verarbeitung von Aufgaben ordnungsgemäß serialisiert und deserialisiert werden. Wenn Ihre Warteschlangenaufgabenklasse im Konstruktor ein Eloquent-Modell empfängt, werden nur Eigenschaften, die dieses Modell identifizieren, in die Warteschlange serialisiert. Wenn die Aufgabe tatsächlich ausgeführt wird, ruft das Warteschlangensystem automatisch das vollständige Modell aus der Datenbank ab. Dieser gesamte Prozess ist für Ihre Anwendung völlig transparent, wodurch einige der Probleme vermieden werden, die mit der Serialisierung vollständiger Eloquent-Musterinstanzen einhergehen.
Wenn die Warteschlange Aufgaben verarbeitet, wird die Methode handle
aufgerufen. Hier können wir auch den Parametertyphinweis der Methode handle
verwenden, damit der Servicecontainer von Laravel automatisch abhängige Objekte einfügt.
Wenn Sie die volle Kontrolle darüber haben möchten, wie der Container abhängige Objekte in die handle
-Methode einfügt, können Sie die bindMethod
-Methode des Containers verwenden. Die Methode bindMethod
akzeptiert Aufgaben- und Containerrückrufe. Obwohl die handle
-Methode direkt im Rückruf aufgerufen werden kann, wird empfohlen, sie vom Dienstanbieter aufzurufen:
use App\Jobs\ProcessPodcast; $this->app->bindMethod(ProcessPodcast::class.'@handle', function ($job, $app) { return $job->handle($app->make(AudioProcessor::class)); });
{note} Binärdaten wie Bildinhalte sollten in die Warteschlange gestellt werden Aufgabe vor Sie müssen die Methode
base64_encode
verwenden, um sie zu konvertieren. Andernfalls wird die Aufgabe möglicherweise nicht korrekt in JSON serialisiert, wenn sie in die Warteschlange gestellt wird.
Aufgaben verteilen
Sobald Sie Ihre Aufgabenklasse geschrieben haben, können Sie sie mit einer eigenen dispatch
-Methode verteilen. Die an die Methode dispatch
übergebenen Parameter werden an den Aufgabenkonstruktor übergeben:
<?php namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller{ /** * 存储一个新的播客节目。 * * @param Request $request * @return Response */ public function store(Request $request) { // 创建播客... ProcessPodcast::dispatch($podcast); } }
Verzögerter Versand
Wenn Sie die Ausführung Ihrer Warteschlangenaufgabe verzögern möchten, können Sie beim Verteilen der Aufgabe die Methode delay
verwenden. Lassen Sie uns beispielsweise eine Aufgabe detailliert beschreiben, die erst nach zehn Minuten ausgeführt wird:
<?php namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller;class PodcastController extends Controller{ /** * 存储一个新的播客节目。 * * @param Request $request * @return Response */ public function store(Request $request) { // 创建播客... ProcessPodcast::dispatch($podcast) ->delay(now()->addMinutes(10)); } }
{note} Der Amazon SQS-Warteschlangendienst hat eine maximale Latenz von 15 Minuten.
Synchrone Planung
Wenn Sie Warteschlangenaufgaben sofort (synchron) ausführen möchten, können Sie diese verwenden dispatchNow
Methode. Bei Verwendung dieser Methode wird die Warteschlangenaufgabe nicht in die Warteschlange gestellt und sofort im aktuellen Prozess ausgeführt:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Jobs\ProcessPodcast; use App\Http\Controllers\Controller; class PodcastController extends Controller{ /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatchNow($podcast); } }
Workchain
Arbeitsketten ermöglichen es Ihnen, gezielt eine Liste von Aufgaben in der Warteschlange zu definieren, die nacheinander ausgeführt werden. Sobald eine Aufgabe in der Sequenz fehlschlägt, wird die verbleibende Arbeit nicht ausgeführt. Um eine Arbeitskette auszuführen, können Sie die Methode withChain
für eine zuteilbare Aufgabe verwenden:
ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch();
{note} Das Löschen einer Warteschlangenaufgabe mit der Methode
$this->delete()
verhindert nicht, dass die Arbeitskettenaufgabe ausgeführt wird ausführen. Die Ausführung der Arbeitskette wird nur dann beendet, wenn die Ausführung einer Aufgabe in der Arbeitskette fehlschlägt.
Workchain-Verbindungen und Warteschlangen
Wenn Sie Standardverbindungen und Warteschlangen für Workchains definieren möchten, können Sie die Methoden allOnConnection
und allOnQueue
verwenden. Diese Methoden geben die Verbindung und Warteschlange der gewünschten Warteschlange an – es sei denn, die Warteschlangenaufgabe ist explizit einer anderen Verbindung/Warteschlange zugewiesen:
ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch()->allOnConnection('redis')->allOnQueue('podcasts');
Maßgeschneiderte Verbindungen & Warteschlange
Aufgaben auf bestimmte Warteschlangen verteilen
Durch die Verteilung von Aufgaben auf verschiedene Warteschlangen können Sie Ihre Warteschlangenaufgaben „kategorisieren“ und sogar Aufgaben verschiedenen Warteschlangen zuweisen. Anzahl der Aufgaben. Denken Sie daran, dass dadurch Aufgaben nicht an verschiedene Verbindungen in der von Ihnen definierten Warteschlangenkonfigurationsdatei weitergeleitet werden, sondern an eine einzelne Verbindung. Um eine Warteschlange anzugeben, verwenden Sie beim Verteilen von Aufgaben die Methode onQueue
:
<?php namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller{ /** * 存储一个新的播客节目。 * * @param Request $request * @return Response */ public function store(Request $request) { // 创建播客... ProcessPodcast::dispatch($podcast)->onQueue('processing'); } }
Aufgaben an die angegebene Verbindung verteilen
Wenn Sie an einer Verbindung mit mehreren Warteschlangen arbeiten , können Sie die Verbindung angeben, an die die Aufgabe verteilt wird. Um eine Verbindung anzugeben, verwenden Sie beim Versenden der Aufgabe die Methode onConnection
:
<?php namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller{ /** * 存储一个新播客节目。 * * @param Request $request * @return Response */ public function store(Request $request) { // 创建播客... ProcessPodcast::dispatch($podcast)->onConnection('sqs'); } }
Natürlich können Sie die Methoden onConnection
und onQueue
verketten, um die Verbindung und die Warteschlange anzugeben.
ProcessPodcast::dispatch($podcast) ->onConnection('sqs') ->onQueue('processing');
Geben Sie die maximale Anzahl von Aufgabenversuchen/Timeout-Wert an
Maximale Anzahl von Versuchen
Die Angabe der maximalen Anzahl von Versuchen für eine Aufgabe kann über < angegeben werden 🎜>Option des Artisan-Befehls:--tries
php artisan queue:work --tries=3Vielleicht möchten Sie eine detailliertere Verarbeitung der maximalen Anzahl von Aufgabenversuchen durch die Aufgabenklasse selbst durchführen. Wenn die maximale Anzahl von Versuchen in der Task-Klasse definiert ist, wird diese vor dem Wert in der Befehlszeile angegeben:
<?phpnamespace App\Jobs;class ProcessPodcast implements ShouldQueue{ /** * 任务可以尝试的最大次数。 * * @var int */ public $tries = 5;}basierend auf Zeitversuchen Als Alternative zur Definition, wie oft eine Aufgabe versucht wird, bevor sie fehlschlägt, können Sie ein Aufgaben-Timeout definieren. Auf diese Weise kann die Aufgabe innerhalb eines bestimmten Zeitrahmens unbegrenzt oft versucht werden. Um eine Zeitüberschreitung für eine Aufgabe zu definieren, fügen Sie Ihrer Aufgabenklasse eine
-Methode hinzu: retryUntil
/** * 定义任务超时时间 * * @return \DateTime */ public function retryUntil(){ return now()->addSeconds(5); }
{tip} Sie könnenTimeoutauch in Ihrer Warteschlangenereignis-Listener-Methode verwenden.
retryUntil
{note}Ebenso kann der Wert der maximalen Sekundenanzahl für die Aufgabenausführung übergeben werden Artisan-BefehlszeilenoptionFunktion optimiert für PHP 7.1 und
timeout
PHP-Erweiterungen.pcntl
angegeben. --timeout
php artisan queue:work --timeout=30Möglicherweise möchten Sie jedoch auch ein Timeout in der Task-Klasse selbst definieren. Wenn in der Aufgabenklasse angegeben, ist die Priorität höher als in der Befehlszeile:
<?php namespace App\Jobs;class ProcessPodcast implements ShouldQueue{ /** * 任务可以执行的最大秒数 (超时时间)。 * * @var int */ public $timeout = 120;}
Frequenzbegrenzung
{note} Diese Funktion erfordert, dass Ihre Anwendung den Redis-Server verwenden kann
Wenn Ihre Anwendung Redis verwendet, können Sie Zeit oder Parallelität verwenden Grenzwerte für Ihre Warteschlangenaufgaben. Diese Funktion ist hilfreich, wenn Ihre Warteschlangenaufgaben über eine API verarbeitet werden, die ebenfalls ratenbegrenzt ist.
Mit der Methode throttle
können Sie beispielsweise die Ausführung einer Aufgabe eines bestimmten Typs auf nur 10 Mal alle 60 Sekunden beschränken. Wenn die Sperre nicht erlangt wird, sollten Sie die Aufgabe generell wieder in die Warteschlange stellen, damit sie später erneut versucht werden kann.
Redis::throttle('key')->allow(10)->every(60)->then(function () { // 任务逻辑... }, function () { // 无法获得锁... return $this->release(10); });
{tip} Im obigen Beispiel kann
key
eine beliebige eindeutige identifizierende Zeichenfolge für den Aufgabentyp sein, dessen Häufigkeit Sie begrenzen möchten. Verwenden Sie beispielsweise den Schlüssel eines Widgets basierend auf dem Namen der Aufgabenklasse oder der ID des Eloquent-Modells, mit dem es arbeitet.{note} Durch die Freigabe eingeschränkter Jobs wieder in der Warteschlange erhöht sich immer noch die Gesamtzahl der Jobs
attempts
.
Alternativ können Sie die maximale Anzahl an Aufgaben angeben, die gleichzeitig ausgeführt werden können. Dies kann nützlich sein, wenn eine Aufgabe in einer Warteschlange eine Ressource ändert, die jeweils nur von einer Aufgabe geändert werden kann. Mit der funnel
-Methode können Sie beispielsweise eine Aufgabe eines bestimmten Typs auf jeweils nur einen Prozessor beschränken:
Redis::funnel('key')->limit(1)->then(function () { // 任务逻辑...}, function () { // 无法获得锁... return $this->release(10); });
{tip} Bei Verwendung der Häufigkeitsbegrenzung die Anzahl erfolgreicher Aufgaben Die Zahl der Hinrichtungsversuche ist möglicherweise schwer zu ermitteln. Daher ist es sinnvoll, Häufigkeitsgrenzen mit Zeitgrenzen zu kombinieren.
Fehlerbehandlung
Wenn während der Aufgabenausführung eine Ausnahme auftritt, wird die Aufgabe automatisch freigegeben Warteschlange, um es erneut zu versuchen. Die Aufgabe wird freigegeben, bis die von der Anwendung maximal zulässige Anzahl von Wiederholungsversuchen erreicht ist. Der maximale Wiederholungswert wird durch die Option queue:work
des Artisan-Befehls oder in der Task-Klasse definiert. Weitere Informationen zu Ausführungswarteschlangenhandlern finden Sie --tries
unten.
Sie können die Schließung auch direkt aufrufen, anstatt die Aufgabenklasse in die Warteschlange einzuplanen. Dies ist nützlich für schnelle, einfache Aufgaben, die ausgeführt werden müssen:
$podcast = App\Podcast::find(1); dispatch(function () use ($podcast) { $podcast->publish(); });
Wenn ein Abschluss an eine Warteschlange gesendet wird, wird der Codeinhalt des Abschlusses kryptografisch signiert, sodass er während der Übertragung nicht geändert werden kann.
Ausführen eines Warteschlangenhandlers
Laravel enthält einen Warteschlangenhandler zum Ausführen von Aufgaben, die in die Warteschlange verschoben werden. Sie können den Befehl queue:work
Artisan verwenden, um den Prozessor auszuführen. Beachten Sie, dass der queue:work
-Befehl, sobald er ausgeführt wird, so lange weiter ausgeführt wird, bis er manuell gestoppt oder das Terminal geschlossen wird.
php artisan queue:work
{Tipp} Damit der
queue:work
-Prozess im Hintergrund läuft, sollten Sie einen Prozessmanager wie Supervisor verwenden, um sicherzustellen, dass der Warteschlangenprozessor nicht aufhört zu laufen
Denken Sie daran, dass der Warteschlangenhandler ein residenter Prozess ist und den Status der gestarteten Anwendung im Speicher hält. Daher werden sie nach dem Start keine Änderungen an Ihrem Code bemerken. Denken Sie also bei Ihrer erneuten Bereitstellung daran, Ihre Warteschlangenhandler neu zu starten.
Verbindungen und Warteschlangen angeben
Sie können auch angeben, welche Warteschlangenverbindung die Warteschlange hat welcher Prozessor verwendet werden soll. Der an work
übergebene Verbindungsname sollte mit einer der in Ihrer config/queue.php
-Konfigurationsdatei definierten Verbindungen übereinstimmen.
php artisan queue:work redis
Sie können Ihren Warteschlangenhandler sogar so anpassen, dass er nur die in der Verbindung angegebene Warteschlange ausführt. Wenn beispielsweise alle Ihre E-Mails von der durch redis
verbundenen emails
-Warteschlange verarbeitet werden, können Sie mit dem folgenden Befehl einen Prozessor starten, der nur für diese Warteschlange ausgeführt wird:
php artisan queue:work redis --queue=emails
ausführen Die Option „Einzelaufgabe“
--once
wird verwendet, um den Warteschlangenprozessor zu veranlassen, nur eine einzelne Aufgabe in der Warteschlange zu verarbeiten.
php artisan queue:work --once
Alle Aufgaben in der Warteschlange verarbeiten und dann beenden
--stop-when-empty
Mit der Option kann der Warteschlangenprozessor so verarbeitet werden, dass er alle Aufgaben verarbeitet und dann ordnungsgemäß beendet wird. Diese Option ist nützlich, wenn Sie eine Laravel-Warteschlange in einem Docker-Container ausführen, wenn Sie den Container herunterfahren möchten, nachdem die Warteschlange leer ist:
php artisan queue:work --stop-when-empty
Ressourcenhinweise
Hintergrundaufbewahrung Die verbleibenden Warteschlangenhandler „starten“ das Framework nicht neu, nachdem jede Aufgabe ausgeführt wurde. Daher sollten Sie nach Abschluss jeder Aufgabe überschüssige Ressourcen freigeben. Wenn Sie beispielsweise eine Bildverarbeitung mit der GD-Bibliothek durchführen, sollten Sie imagedestroy
verwenden, um den Speicher freizugeben, wenn Sie fertig sind.
Warteschlangenpriorität
Manchmal möchten Sie möglicherweise die Warteschlangenausführung priorisieren. Beispielsweise können Sie in config/queue.php
die Priorität der redis
-Warteschlange der queue
-Verbindung von default
auf low
festlegen. Gelegentlich möchten Sie jedoch möglicherweise eine Aufgabe wie folgt in die high
-Warteschlange verschieben:
dispatch((new Job)->onQueue('high'));
muss einen Handler ausführen, um die Aufgaben in der low
-Warteschlange zu bestätigen, bis alle high
-Warteschlangenaufgaben abgeschlossen sind . Wenn Sie die Ausführung fortsetzen, können Sie eine durch Kommas getrennte Liste von Warteschlangennamen als Argumente an den Befehl work
übergeben.
php artisan queue:work --queue=high,low
Warteschlangenprozessoren und Bereitstellung
Da Warteschlangenprozessoren residente Prozesse sind, werden sie nicht von Ihren Codeänderungen betroffen sein angewandt. Daher besteht die einfachste Möglichkeit zum Bereitstellen einer Anwendung, die einen Warteschlangenprozessor verwendet, darin, den Warteschlangenprozessor während des Bereitstellungsprozesses neu zu starten. Sie können alle Warteschlangenprozessoren mithilfe der Methode queue:restart
ordnungsgemäß neu starten:
php artisan queue:restart
Dieser Befehl weist alle Warteschlangenprozessoren an, nach Abschluss der aktuellen Aufgabe ordnungsgemäß abzubrechen, sodass keine Aufgaben verloren gehen. Da der Warteschlangenhandler nach der Ausführung von queue:restart
beendet wird, sollten Sie einen Prozessmanager wie Supervisor ausführen, um den Warteschlangenhandler automatisch neu zu starten.
{tip} Die Warteschlange verwendet Cache, um Neustartsignale zu speichern. Sie sollten daher sicherstellen, dass Sie den Cache-Treiber konfigurieren, bevor Sie diese Funktion verwenden.
Aufgabenablauf und Zeitüberschreitung
Aufgabenablauf
In deinemconfig/queue.php
In der Konfigurationsdatei definiert jede Warteschlangenverbindung eine retry_after
-Option. Diese Option gibt an, wie lange die Warteschlangenverbindung auf eine Aufgabe warten soll, bevor sie sie erneut versucht. Wenn beispielsweise der Wert von retry_after
auf 90
gesetzt ist, wird die Aufgabe nach 90 Sekunden Ausführungszeit wieder in die Warteschlange gestellt, anstatt sie zu löschen. Im Allgemeinen sollten Sie den Wert von retry_after
auf den Wert festlegen, von dem Sie glauben, dass die Ausführung Ihrer Aufgabe wahrscheinlich am längsten dauert.
{note} Der Wert
retry_after
existiert nicht nur in Amazon SQS. SQS wird die Aufgabe basierend auf dem in der AWS-Konsole konfigurierten Standardwert für das sichtbare Zeitlimit wiederholen.
Prozessor-Timeout
queue:work
Der Artisan-Befehl enthält eine --timeout
-Option. Die Option --timeout
gibt an, wie lange der Warteschlangenmaster von Laravel wartet, bevor er einen untergeordneten Prozess abbricht, der eine Aufgabe ausführt. Manchmal kann ein untergeordneter Prozess aus verschiedenen Gründen „einfrieren“, beispielsweise weil er nicht auf eine externe HTTP-Anfrage reagiert. Die Option --timeout
entfernt Prozesse, die länger als die angegebene Zeit eingefroren waren. Das Konfigurationselement
php artisan queue:work --timeout=60
retry_after
und die Befehlszeilenkonfiguration --timeout
unterscheiden sich nicht, aber ihre gemeinsame Verwendung kann sicherstellen, dass die Aufgabe nicht verloren geht und die Aufgabe nur einmal erfolgreich ausgeführt wird.
{note} Der Wert von
--timeout
sollte mindestens ein paar Sekunden kürzer sein als der Wert, den Sie inretry_after
konfiguriert haben. Dadurch wird sichergestellt, dass der Prozessor immer abbricht, bevor eine Aufgabe erneut versucht werden kann. Wenn Ihr--timeout
-Wert länger als derretry_after
-Wert ist, wird Ihre Aufgabe möglicherweise zweimal ausgeführt.
Ruhezeit des Warteschlangenprozesses
Wenn eine Aufgabe in der Warteschlange verfügbar ist, verarbeitet der Prozessor die Aufgabe ohne Unterbrechung weiter. Die Option sleep
definiert jedoch, wie lange der Prozessor „schläft“, wenn keine neuen Aufgaben anstehen. Während der Prozessor schläft, verarbeitet er keine neuen Aufgaben – Aufgaben werden ausgeführt, wenn der Warteschlangenprozessor erneut gestartet wird.
php artisan queue:work --sleep=3
Supervisor-Konfiguration
Install Supervisor
Supervisor ist Linux Ein Prozessmonitor unter dem Betriebssystem, der sein kann queue:work
Automatischer Neustart, wenn es hängt. Um Supervisor unter Ubuntu zu installieren, können Sie den folgenden Befehl verwenden:
sudo apt-get install supervisor
{Tipps} Wenn Sie Schwierigkeiten haben, Supervisor zu konfigurieren, können Sie die Verwendung von Laravel Forge in Betracht ziehen Installieren und konfigurieren Sie Supervisor automatisch für Ihr Laravel-Projekt.
Supervisor konfigurieren
Supervisor-Konfigurationsdateien befinden sich normalerweise im Verzeichnis /etc/supervisor/conf.d
. In diesem Verzeichnis können Sie eine beliebige Anzahl von Konfigurationsdateien erstellen, um zu steuern, wie der Supervisor Ihren Prozess überwacht. Erstellen Sie beispielsweise eine laravel-worker.conf
-Datei, um einen queue:work
-Prozess zu starten und zu überwachen:
[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 autostart=true autorestart=true user=forge numprocs=8 redirect_stderr=true stdout_logfile=/home/forge/app.com/worker.log
In diesem Beispiel gibt die numprocs
-Direktive Supervisor an, 8 queue:work
-Prozesse automatisch auszuführen und zu überwachen Starten Sie sie neu, wenn sie hängen bleiben. Sie sollten den command
-Teil der queue:work sqs
-Optionen ändern, um Ihre gewünschte Warteschlangenverbindung darzustellen.
Supervisor starten
Nachdem die Konfigurationsdatei erstellt wurde, können Sie den folgenden Befehl verwenden, um die Supervisor-Konfiguration zu aktualisieren und den Vorgang zu starten:
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start laravel-worker:*
Weitere Informationen zu Supervisor finden Sie hier Vorgesetzter Dokumentation.
Umgang mit fehlgeschlagenen Aufgaben
Manchmal werden Ihre Aufgaben in der Warteschlange nicht ausgeführt. Entspanne deinen Geist, gute Dinge kommen nur mit der Zeit. Laravel enthält eine praktische Methode, um anzugeben, wie oft eine Aufgabe maximal versucht werden soll. Wenn eine Aufgabe die maximale Anzahl an Versuchen erreicht hat, wird sie in die Datenbanktabelle failed_jobs
eingefügt. Um die Datenbankmigrationstabelle failed_jobs
zu erstellen, können Sie den Befehl queue:failed-table
verwenden:
php artisan queue:failed-table php artisan migrate
. Wenn Sie dann den Warteschlangenarbeiter ausführen, sollten Sie queue:work
im verwenden --tries
Befehl Der Schalter gibt an, wie oft die Aufgabe maximal ausgeführt werden soll. Wenn für die Option --tries
kein Wert angegeben ist, wird eine Endlosschleife versuchen, die Aufgabe auszuführen:
php artisan queue:work redis --tries=3
Aufräumen danach Aufgabenfehler
Sie können es direkt in der Aufgabenklasse definierenfailed
Methode, mit der Sie Bereinigungsarbeiten für eine Aufgabe durchführen können, wenn diese fehlschlägt. Dies ist ein hervorragender Ort, um Benachrichtigungen an den Benutzer zu senden oder alle von der Aufgabe ausgeführten Aktionen fortzusetzen. Das Exception
, das zum Fehlschlagen der Aufgabe geführt hat, wird an die Methode failed
übergeben:
<?php namespace App\Jobs; use Exception;use App\Podcast; use App\AudioProcessor; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class ProcessPodcast implements ShouldQueue{ use InteractsWithQueue, Queueable, SerializesModels; protected $podcast; /** * 创建任务实例 * * @param Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; } /** * 执行任务 * * @param AudioProcessor $processor * @return void */ public function handle(AudioProcessor $processor) { // 上传播客…… } /** * 任务失败的处理过程 * * @param Exception $exception * @return void */ public function failed(Exception $exception) { // 给用户发送任务失败的通知,等等…… } }
Aufgabenfehlerereignis
Wenn Sie ein aufrufbares Ereignis registrieren möchten, wenn eine Aufgabe fehlschlägt, können Sie die Methode Queue::failing
verwenden. Diese Veranstaltung ist ein guter Zeitpunkt, um Ihr Team per E-Mail oder Slack zu benachrichtigen. Beispielsweise können wir in Laravel ein Rückrufereignis an AppServiceProvider
anhängen:
<?php namespace App\Providers; use Illuminate\Support\Facades\Queue; use Illuminate\Queue\Events\JobFailed; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * 启动任意服务。 * * @return void */ public function boot() { Queue::failing(function (JobFailed $event) { // $event->connectionName // $event->job // $event->exception }); } /** * 注册服务提供者。 * * @return void */ public function register() { // } }
Retry the failed task
Um alle Aufgaben anzuzeigen, die in der Datentabelle failed_jobs
platziert wurden, können Sie verwenden Artisan-Befehl queue:failed
: Der Befehl
php artisan queue:failed
queue:failed
listet die Aufgaben-ID, die Warteschlange und die Fehlerzeit auf. Die Aufgaben-ID kann verwendet werden, um fehlgeschlagene Aufgaben erneut zu versuchen. Um beispielsweise eine Aufgabe mit der Aufgaben-ID 5
erneut zu versuchen, verwenden Sie den folgenden Befehl:
php artisan queue:retry 5
Um alle fehlgeschlagenen Aufgaben erneut zu versuchen, führen Sie den Befehl queue:retry
aus und übergeben Sie all
als ID:
php artisan queue:retry all
Wenn Sie eine fehlgeschlagene Aufgabe löschen möchten, verwenden Sie queue:forget
Befehl:
php artisan queue:forget 5
Um alle fehlgeschlagenen Aufgaben zu löschen, verwenden Sie queue:flush
Befehl:
php artisan queue:flush
Fehlende Modelle ignorieren
Beim Einfügen eines Eloquent-Modells in eine Aufgabe wird das Modell automatisch serialisiert, bevor es in die Warteschlange gestellt und wiederhergestellt wird, wenn die Aufgabe ausgeführt wird. Wenn das Modell jedoch gelöscht wird, während die Aufgabe auf ihre Ausführung wartet, schlägt die Aufgabe möglicherweise fehl und löst ModelNotFoundException
aus.
Der Einfachheit halber können Sie Aufgaben mit fehlenden Modellen automatisch löschen, indem Sie das deleteWhenMissingModels
-Attribut der Aufgabe auf true
setzen.
/** * 如果模型缺失即删除任务。 * * @var bool */ public $deleteWhenMissingModels = true;
Aufgabenereignis
Durch Verwendung der Methoden Queue
und before
in der after
-Fassade , Sie können einen Rückruf vor und nach der Ausführung einer Warteschlangenaufgabe angeben. Diese Rückrufe sind eine hervorragende Gelegenheit, zusätzliche Protokolle hinzuzufügen oder Statistiken zu verbessern. Normalerweise sollten Sie diese Methoden im Dienstanbieter aufrufen. Zum Beispiel können wir Laravels AppServiceProvider
verwenden:
<?php namespace App\Providers; use Illuminate\Support\Facades\Queue; use Illuminate\Support\ServiceProvider; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; class AppServiceProvider extends ServiceProvider{ /** * 引导启动任意应用服务。 * * @return void */ public function boot() { Queue::before(function (JobProcessing $event) { // $event->connectionName // $event->job // $event->job->payload() }); Queue::after(function (JobProcessed $event) { // $event->connectionName // $event->job // $event->job->payload() }); } /** * 注册服务提供者。 * * @return void */ public function register() { // } }
Mit der Queue
-Methode an der looping
-Fassade kann ein Rückruf ausgeführt werden, bevor der Prozessor versucht, die Aufgabe abzurufen. Beispielsweise möchten Sie möglicherweise einen Abschluss verwenden, um eine zuvor fehlgeschlagene Aufgabe rückgängig zu machen, bei der die Transaktion noch nicht abgeschlossen wurde:
Queue::looping(function () { while (DB::transactionLevel() > 0) { DB::rollBack(); } });