Jak pozastavit a obnovit práci ve frontě v systému Laravel
V této příručce se dozvíte, jak pozastavit a obnovit práci ve frontě Laravel na vyžádání.
Budeme pracovat v kontextu dlouho běžících queue:work procesy spravované z rozhraní CLI.
Uvidíte, jak se při pozastavování pracovníků zaměřit na konkrétní připojení a fronty.
Uvidíte také, jak pozastavit fronty na dobu neurčitou nebo na pevně stanovenou dobu z kódu Artisan i z kódu aplikace.
Co znamená pozastavení fronty
Než se dotknete jakýchkoli příkazů, je dobré si ujasnit, co vlastně fronta "paused" v Laravelu dělá:
- Pauza je na frontu a na připojení, nikoli globálně pro všechny fronty.
- Pracovníci, kteří již pracují dokončit práci, kterou právě zpracovávají..
- Po dokončení aktuální úlohy pracovníci přestat stahovat nová pracovní místa z pozastavené fronty.
- Samotný pracovní proces stále běží; neukončí se nebo se nezabije.
- Po obnovení fronty začnou pracovníci okamžitě opět vybírat úlohy z této fronty.
Pozastavení je tedy způsob, jak dočasně pozastavit frontu, aniž byste se dotkli správce procesů nebo pracovních procesů.
Pozastavení a obnovení fronty pomocí nástroje Artisan
Nejpřímější způsob pozastavení a obnovení front je prostřednictvím nástroje Artisan. Obvykle se tak děje v produkčních shellech nebo skriptech pro nasazení.
Spuštění pracovníka pro konkrétní připojení a frontu
Nejprve předpokládejte, že máte pracovníka, který zpracovává frontu. Například:
php artisan queue:work database --queue=default
Tento pracovník používá database a naslouchá připojení fronty default fronta.
Název spojení pochází z config/queue.phpa název fronty je název, který jste nakonfigurovali nebo použili při odesílání úloh.
Dokud bude tento proces spuštěn, bude vybírat úlohy z fronty. database připojení default fronta.
Pozastavení fronty z rozhraní CLI
Chcete-li frontu pozastavit, použijte příkaz queue:pause a předat příkaz jediný argument v connection:queue formát:
php artisan queue:pause database:default
Klíčové body:
databaseje název připojení.defaultje název fronty.- Všichni pracovníci, kteří zpracovávají zakázky z
database/defaultdokončí svou současnou práci. - Po dokončení této práce budou ne načítat nové úlohy z této fronty, dokud nebude obnovena.
Pokud používáte Redis s vlastním názvem fronty, vypadá pozastavení této fronty takto:
php artisan queue:pause redis:emails
Pracovníci, kteří poslouchají redis a zpracování emails fronta přestane přijímat nová pracovní místa od emails, ale mohou nadále zpracovávat jiné fronty, pokud jsou nakonfigurovány tak, aby naslouchaly více frontám.
Obnovení fronty z rozhraní CLI
Chcete-li obnovit zpracování úlohy v pozastavené frontě, použijte příkaz queue:continue se stejným connection:queue syntaxe:
php artisan queue:continue database:default
Po spuštění tohoto příkazu:
- Pracovníci, kteří byli nečinní, protože
database:defaultbyla pozastavena, začne opět vybírat nové úlohy z této fronty. - Pracovní místa, která se nahromadila na
database/defaultkdyž byl pozastavený, bude nyní zpracován normálně.
Stejně můžete postupovat i u jakékoli jiné kombinace připojení a fronty. Například:
php artisan queue:continue redis:emails
Tento příkaz k obnovení funguje bez ohledu na to, zda byla fronta pozastavena pomocí nástroje Artisan nebo pomocí kódu aplikace, protože oba příkazy procházejí stejným základním správcem fronty.
Programové pozastavení a obnovení fronty
Někdy chcete frontu pozastavit nebo obnovit. z kódu aplikace místo rozhraní CLI. Můžete například chtít pozastavit frontu, když je překročen limit rychlosti externího rozhraní API nebo když správce přehodí příznak funkce na ovládacím panelu.
Za tímto účelem nabízí Laravel rozhraní API pro pozastavení fronty prostřednictvím příkazu Queue fasády a pod ní ležící QueueManager třída.
Časově neomezené pozastavení fronty v kódu
Chcete-li frontu pozastavit na dobu neurčitou z kódu, můžete zavolat příkaz Queue::pause s názvem připojení a fronty:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Illuminate\Support\Facades\Queue; class QueueAdminController{ public function pauseDefaultDatabaseQueue(Request $request) { // Pause the "default" queue on the "database" connection indefinitely Queue::pause('database', 'default'); return response()->json([ 'status' => 'ok', 'message' => 'database:default queue paused', ]); }}
Co je v tomto příkladu důležité:
Queue::pause('database', 'default')pozastaví frontu identifikovanou tímto připojení a fronta.- Pauza je neurčitý. Fronta zůstane pozastavena, dokud ji výslovně neobnovíte.
- Tuto funkci můžete volat odkudkoli v aplikaci: z řadičů, příkazů, služeb nebo úloh.
Chcete-li obnovit stejnou frontu z kódu, zavolejte příkaz Queue::resume:
Queue::resume('database', 'default');
Můžete bez obav volat Queue::resume i když fronta není aktuálně pozastavena. Jednoduše zajistí, aby byl příznak pozastaveno vymazán.
Pozastavení fronty na pevně stanovenou dobu
Laravel také umožňuje pozastavit frontu po určitou dobu pomocí Queue::pauseFor.
Tato metoda přijímá tři argumenty:
-
Na stránkách název připojení.
-
Na stránkách název fronty.
-
A TTL (doba života) hodnotu, která může být:
- Celé číslo sekund.
- A
DateTimeInterfaceinstance. - A
DateIntervalinstance.
Zde je jednoduchý příklad, který pozastaví frontu na 60 sekund:
use Illuminate\Support\Facades\Queue; // Pause for 60 secondsQueue::pauseFor('redis', 'default', 60);
Pauzu můžete vyjádřit také pomocí DateTimeInterface uvedením přesného okamžiku, kdy má pauza skončit:
use Illuminate\Support\Facades\Queue; // Pause until five minutes from nowQueue::pauseFor('redis', 'default', now()->addMinutes(5));
Nebo pomocí DateInterval:
use DateInterval;use Illuminate\Support\Facades\Queue; // Pause for 45 seconds via DateIntervalQueue::pauseFor('redis', 'default', new DateInterval('PT45S'));
Když používáte pauseFor:
- Laravel nastaví interní příznak, který označí frontu jako pozastavenou pro daný TTL.
- Dokud je příznak aktivní, pracovníci po dokončení aktuálně zpracovávaných úloh z této fronty nové úlohy nevybírají.
- Po uplynutí TTL příznak automaticky zmizí a pracovníci budou frontu opět považovat za aktivní.
- Nemusíte volat
Queue::resumepo vypršení TTL, i když jej můžete zavolat ručně, pokud chcete obnovit dříve.
Příklad: pozastavení fronty při návratu externího rozhraní API 429
Velmi praktický případ použití pro pauseFor zpracovává rozhraní API s omezenou rychlostí, které vrací protokol HTTP 429 se znakem Retry-After záhlaví.
Zde je zjednodušený příklad úlohy, která využívá takové rozhraní API:
<?php namespace App\Jobs; use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Bus\Dispatchable;use Illuminate\Queue\InteractsWithQueue;use Illuminate\Queue\SerializesModels;use Illuminate\Support\Facades\Http;use Illuminate\Support\Facades\Queue; class SyncExternalData implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle(): void { $response = Http::get('https://example.com/api/data'); if ($response->status() === 429) { $retryAfter = (int) $response->header('Retry-After', 60); // Pause the queue that is processing this job for the Retry-After period Queue::pauseFor($this->queueConnection(), $this->queueName(), $retryAfter); // Optionally release this job so it can be retried later $this->release($retryAfter); return; } // Normal processing logic for successful responses... } protected function queueConnection(): string { return $this->connection ?? config('queue.default'); } protected function queueName(): string { return $this->queue ?? 'default'; }}
Důležité informace:
Queue::pauseFor(...)je volána se stejným připojením a frontou, ve které je tato úloha spuštěna.- TTL je převzato z
Retry-Afterzáhlaví, pokud je k dispozici, nebo výchozí hodnota 60 sekund. release($retryAfter)řekne frontě, aby úlohu zopakovala po stejné prodlevě, takže zpracování bude pokračovat po skončení pauzy.- Ostatní úlohy ve stejné frontě budou také pozastaveny, dokud nevyprší TTL.
Tento vzor můžete upravit pro jakoukoli situaci, kdy potřebujete na chvíli zrušit celou frontu.
Kontrola, zda je fronta pozastavena
Někdy chcete pouze zjistit, zda je fronta aktuálně pozastavena, abyste se mohli rozhodnout v kódu. K tomu můžete použít Queue::isPaused:
use Illuminate\Support\Facades\Queue; if (Queue::isPaused('redis', 'default')) { // Maybe skip dispatching some jobs or show a warning in the UI}
Tato metoda vrací true pokud je fronta pozastavena (buď na dobu neurčitou, nebo do budoucna) a false v opačném případě.
Jak funguje spolupráce mezi rozhraním CLI a pozastavením na základě kódu
Příkazy Artisan a Queue facade používají stejného správce fronty a stejný stav pauzy.
To znamená:
- Frontu můžete pozastavit z kódu pomocí příkazu
Queue::pauseorQueue::pauseFora poté jej obnovit pomocíphp artisan queue:continue. - Můžete pozastavit pomocí
php artisan queue:pausea později pokračovat z kódu pomocíQueue::resume. Queue::isPausedodráží stav bez ohledu na to, jak byla pauza zahájena.
Protože je stav pauzy sdílený, nemusíte se obávat, že by si různé mechanismy vzájemně odporovaly.
Závěr
Viděli jste, jak Laravel umožňuje pozastavit a obnovit konkrétní fronty bez zastavení pracovních procesů.
Pozastavení fronty můžete ovládat ze systému Artisan pomocí příkazu queue:pause a queue:continue s jednoduchým connection:queue argument.
Fronty můžete také pozastavit na dobu neurčitou nebo na přesně stanovenou dobu v kódu pomocí příkazu Queue a v případě potřeby zkontrolovat aktuální stav pauzy.
Pomocí těchto nástrojů můžete pauzování hluboce integrovat do svých pracovních postupů, nasazení a strategií omezování rychlosti, aniž byste museli zasahovat do nastavení dohledu nad pracovníky.