Warteschlange


Warteschlange

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=3

Vielleicht 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önnen

auch in Ihrer Warteschlangenereignis-Listener-Methode verwenden. retryUntil

Timeout

{note}

Funktion optimiert für PHP 7.1 und timeoutPHP-Erweiterungen.pcntl

Ebenso kann der Wert der maximalen Sekundenanzahl für die Aufgabenausführung übergeben werden Artisan-Befehlszeilenoption

angegeben. --timeout

php artisan queue:work --timeout=30

Mö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.

Warteschlangenschließung

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 in retry_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 der retry_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();   
       }
    });
Dieser Artikel erschien zuerst auf der Website LearnKu.com.