- A Laravel egy egységes várólista API-t kínál több illesztőprogrammal (adatbázis, Redis, SQS…), valamint a kapcsolatok és a logikai várólisták elkülönítésével.
- A feladatok lehetővé teszik a nagy teljesítményű feladatok háttérbe helyezését, támogatva a modellek szerializálását, a köztes szoftvereket, az egyszeri feladatokat, a titkosítást, a kötegeket és a karakterláncokat.
- A munkavégző programokat a queue:work, a Supervisor és olyan parancsok segítségével lehet kezelni, mint a queue:pause/queue:continue, amelyek szabályozzák az újrapróbálkozásokat, az időtúllépéseket és a prioritásokat.
- Létezik egy komplett ökoszisztéma a hibákhoz, monitorozáshoz és teszteléshez (failed_jobs, queue:retry, queue:monitor, Queue::fake), amely megbízhatóvá teszi a várólisták használatát éles környezetben.
A Laravelben a várólisták kezelése szinte kötelező minden komolyabb projektben: e-mailek küldése, CSV fájlok feldolgozása, PDF-ek generálása, képek átméretezése, külső API-k meghívása… Ha mindezt a fő HTTP kérésben végezzük el, a weboldal lelassul, 500 hiba jelenik meg, és a felhasználó kétségbeesetten bámulja az üres képernyőt.
A jó hír az, hogy a Laravel egy hatékony és rugalmas sorbanállási infrastruktúrát kínál , amely lehetővé teszi a nehéz feladatok háttérfolyamatokra való delegálását, azok prioritás szerinti kezelését, kötegekbe csoportosítását, monitorozását, hiba esetén újrapróbálkozást, sőt, karbantartás céljából akár a munkafolyamatok ideiglenes szüneteltetését is . Nézzük meg közelebbről (és ne hagyjunk ki semmit), hogyan hozhatjuk ki belőle a legtöbbet, beleértve a szüneteltetést, az újraindítást és a viselkedésének szabályozását éles környezetben.
Alapfogalmak: kapcsolatok, várólisták és illesztőprogramok
Laravelben, mielőtt bármit is szüneteltetnél, meg kell értened a különbséget a következők között: sorkapcsolatok és maguk a sorok. -Ban config/queue.php van egy tömböd connections ahol definiálod az egyes backendeket: adatbázis, redis, beanstalkd, sqs, szinkron, null, feladatátvétel, rabbitmq (ha hozzáadod) stb.
Minden kapcsolathoz több is tartozhat logikai sorok (olyan nevek, mint default, emails, high, low, importsAz attribútum queue Minden kapcsolat jelzi, hogy melyik az alapértelmezett várakozási sor, ahová a feladatok kerülnek, ha nincs más megadva. onQueue()Így olyan dolgokat tehetsz, mint:
- Gyors sorban állás e-mailekhez vagy rövid tranzakciókhoz.
- Egy másik alacsony prioritású hosszú feladatokhoz, például videók vagy nagyméretű jelentések feldolgozásához.
- Feladattípus szerint szegmentált várólisták:
imports,notificaciones,reportesStb
Amikor elindítod a dolgozót a php artisan queue:workAlapértelmezés szerint a megadott várólistára figyel. alapértelmezett a kiválasztott kapcsolaton. Ha prioritást szeretne beállítani, több vesszővel elválasztott sort is átadhat:
php artisan queue:work redis --queue=high,default,low
Így a feldolgozó először a high , majd a default , és csak ezután a low értékeket dolgozza fel , ami kulcsfontosságú a rendszer betöltésekor, és nem szeretné, hogy egy 30 perces jelentés blokkolja a magas prioritású e-maileket.
Várólista-vezérlők és előfeltételek
A Laravel egységes API-t kínál számos várólista-illesztőprogramhoz , de mindegyiknek megvannak a saját specifikus funkciói és függőségei. A megfelelő illesztőprogram kiválasztása kulcsfontosságú a workerek szüneteltetéséről szóló beszélgetések megvitatása előtt.
Illesztőprogram-adatbázis
A sofőr adatbázis A feladatokat egy SQL táblában tárolja (általában jobsKönnyen beállítható, és tökéletes kisebb projektekhez vagy fejlesztői környezetekhez, ahol nem szeretnél a Redis-szel vagy az SQS-szel babrálni.
Alap lépések:
- A migráció generálása:
php artisan queue:table(vagy újabb verziókban így jelenik megcreate_jobs_tablealapértelmezett). - Futtassa az áttelepítéseket:
php artisan migrate. - konfigurálása QUEUE_CONNECTION=adatbázis a
.envés nyugtázza beconfig/queue.phphogy'default' => env('QUEUE_CONNECTION','database').
Kényelmes és elég robusztus, de sok várólistával és nagy forgalommal szűk keresztmetszettel járhat , mivel minden ugyanazon a relációs adatbázison keresztül megy keresztül.
Redis illesztőprogram
A Redis illesztőprogram a szabványos munkagép éles környezetben. Gyors, támogatja a fejlett funkciókat (zárolás, sebességkorlátozás, atomi zárak, Horizon stb.), és nagyon jól skálázható.
Fontos pontok:
- Redis kapcsolatot kell konfigurálnia a következőben:
config/database.php. - Az opciók
serializerycompressiona Redistől Nem kompatibilisek a sorvezetővel. - Ha használja Redis-klaszterA várólisták neveinek tartalmazniuk kell egy hash taget, például
{default}hogy az adott sorban lévő összes kulcs ugyanabba a nyílásba essen. - A választás
block_forEz lehetővé teszi a dolgozó számára, hogy néhány másodpercig blokkoljon, miközben a feladatokra vár, a folyamatos lekérdezés helyett: CPU-t takarít meg és csökkenti a Redis szerverre irányuló lekérdezések számát.
Például:
'redis' => ,
Ha teszel blokk_for = 0A munkavállaló határozatlan időre blokkolva marad, amíg egy munka fel nem válik elérhetővé, amit érdemes szem előtt tartani, ha azt szeretné, hogy gyorsan reagáljon az olyan jelekre, mint a SIGTERM vagy szüneteltetési parancsok.
Egyéb illesztőprogramok: SQS, Beanstalkd, null, failover…
Az adatbázisok és a redis mellett a Laravel más rendszereket is támogat :
- Amazon SQSFelügyelt sorok az AWS-en, a következők támogatásával: FIFOÜzenetcsoportok, deduplikáció és speciális láthatósági beállítások. SDK szükséges hozzá.
aws/aws-sdk-php. - BeanstalkdNagyon gyors és egyszerű, a csomag használatával
pda/pheanstalk. - szinkronizálni: elvégzi a feladatokat azonnal ugyanabban a folyamatban. Hasznos fejlesztés vagy tesztelés során, de éles környezetben gyakorlatilag olyan, mintha egyáltalán nem használnánk sorokat.
- null: A feladatokat azonnal elveti, amint „elküldésre” kerültek. A várakozási rendszer teljes letiltására szolgál.
- failoverEz lehetővé teszi több kapcsolat konfigurálását, és ha az elsődleges kapcsolat sikertelen, a Laravel megpróbálja a feladatot a listán következőre áthelyezni. Tökéletes olyan környezetekben, ahol a magas rendelkezésre állás kritikus.
A workerek szüneteltetésének és folytatásának szintjén a logika gyakorlatilag ugyanaz, függetlenül a meghajtótól, mivel azt az Artisan parancsokból és a Worker osztályból kezelik , nem pedig a várólista háttérrendszeréből.
Feladatok létrehozása és modell szerializálása
Un Munka Laravelben ez egyszerűen egy osztály, amely egy sorban végrehajtandó feladatot foglal magában. Általában az Artisan segítségével generálják és a következő helyre mentik: app/Jobs.
Létrehozása:
php artisan make:job ProcessPodcast
A generált osztály megvalósítja ShouldQueue és általában tulajdonságokat használ Dispatchable, InteractsWithQueue, Queueable y SerializesModelsA szív a módszerben rejlik handle()amit a munkavállaló tesz, amikor megérkezik a munka.
Különösen hatékony funkció az Eloquent modellek automatikus szerializálása . Ha elfogadunk egy modellt a Job konstruktorban, a Laravel nem adja hozzá a teljes objektumot a várólistához, csak az azonosítóját. Amikor a job feldolgozásra kerül, az adatbázisból rekonstruálja a modellt a betöltött kapcsolataival együtt.
Tipikus példa (pszeudokódban, hogy elkerüljük a szó szerinti ismétlést):
- Építő kapja meg Podcast $podcast.
- A tulajdonság
SerializesModelsAz azonosító mentéséért felelős. - En
handle(AudioProcessor $processor)Te végzed a nehéz munkát (például a hang feldolgozását).
Ha nem szeretné, hogy a modellben lévő kapcsolatok szerializáltak legyenek (így a hasznos terhelés nem lesz hatalmas), használhatja a következőt: $model->withoutRelations() vagy PHP 8-ban az attribútum # az építtető által népszerűsített ingatlanon.
Függőség-injektálás a handle metódusban
További előny, hogy tudsz szolgáltatások közvetlenül a handle metódusba történő befecskendezése (mintha egy vezérlő lenne), mivel a Laravel is használja a szolgáltatástárolót a Jobsban. Például kérhetsz egy AudioProcessorHTTP kliensek, adattárak stb., és a keretrendszer gondoskodik ezek feloldásáról.
Ha ultrafinom szabályozásra van szüksége az ún. handletudod használni Container::bindMethod() egy szolgáltatónál, és magad határozhatod meg a befecskendezési logikát, de a legtöbb esetben nincs szükség ennyire bonyolítani a dolgokat.
Job Middleware
Ahogy az útvonalaknak is van köztes szoftverük, a munkáknak is lehetnek specifikus köztes szoftver amelyek a feladat előtt és után futnak. Ez nagymértékben csökkenti az ismétlődő kódot a metódusokban handle() és különösen hasznos a következőkhöz:
- Sebességkorlátozás a Redis-szel.
- elkerülése átfed olyan művekből, amelyek ugyanazt az erőforrást érintik.
- Rendszeres kivételek instabil API-k esetén.
- Feladatok kihagyása bizonyos feltételek mellett (
Skipköztes szoftver).
A köztes szoftvert általában a következő helyen helyezik el: app/Jobs/Middleware és a metódus visszaadja őket middleware() Jób könyvéből. Koncepcionális példa:
public function middleware(): array { return ;
Speciális típusú feladatok: egyedi, titkosított és zárolt
A Laravel lehetővé teszi bizonyos munkák megjelölését egyedi hogy két azonos példány ne kerüljön egyszerre sorba. Ezt a felület megvalósításával érik el. ShouldBeUnique o ShouldBeUniqueUntilProcessingés támogatja a kulcs definiálását uniqueId() és egy idő uniqueFor.
Ez ideális olyan dolgokhoz, mint:
- Termék keresési indexének újraszámítása: termékenként csak egyszer amíg be nem fejeződik.
- Szinkronizálások külső szolgáltatásokkal, amelyek nem engedélyezik az ugyanazon erőforrásra vonatkozó egyidejű kéréseket.
Alatta a Laravel egy atomzár a gyorsítótárból (Redis, memcached, adatbázis stb.). Kiválaszthatja az adott zárhoz tartozó gyorsítótár-illesztőprogramot is a következővel: uniqueVia().
Ezen felül ott van a felület ShouldBeEncrypted, amellyel azt jelzi, hogy a teljes Munka Add meg a kódodat, mielőtt beállsz a sorbaNagyon hasznos érzékeny adatok továbbításakor, és nem szeretné, hogy azok egyszerű szövegként haladjanak át a Redisen, az SQS-en vagy az adatbázison keresztül.
Feladatok küldése, késleltetése és végrehajtása különböző módokban
Miután meghatároztad a feladatodat, elindíthatod a következővel: Job::dispatch() vezérlőktől, eseményfigyelőktől, Artisan parancsoktól vagy akár lezárásoktól is. A paraméterek, amelyeket átadsz dispatch Egyenesen Jób építőjéhez mennek.
Érdekes variációk:
dispatchIf()ydispatchUnless()hogy a szállítmányt egyetlen sorban kondicionálja.delay()így a feladat egy adott dátumig/időpontig nem dolgozható fel.dispatchAfterResponse()oafterResponse()endispatch()Lezárások, amelyek a végrehajtást a HTTP válasz elküldéséig halasztják, de ugyanazon a PHP folyamaton belül.dispatchSync()a Job szinkron futtatása (a várakozási soron való áthaladás nélkül), de ugyanazon osztály újrafelhasználásával.- Speciális kapcsolatok, mint például
deferredobackgrounda válasz után végrehajtandó, ugyanabban a folyamatban vagy egy új PHP folyamatban.
Végül láncolt metódusokkal adhatja meg a kapcsolatot és a sort. onConnection() y onQueue(), akár a kiküldéskor, akár a Job Builder-en belül.
Finomvezérlés: újrapróbálkozások, visszavonások, időtúllépések és hibakezelés
A Laravelben a várólisták kezelésének egyik fontos része annak eldöntése, hogy hányszor próbáljuk újra a feladatot , mennyi időt várjunk a próbálkozások között, és mikor tekintsük azt sikertelennek.
Opcionális készülékek:
--triesenqueue:workaz adott munkavállaló összes feladatához tartozó próbálkozások maximális számának beállítása (kivéve, ha a feladat sajátot határoz meg)$triesotries()).$triesvagy egy módszertries()a Job osztályban a Job-onkénti vezérléshez.retryUntil()azt mondani: „próbáld újra, ahogy szeretnéd, eddig az időpontig, utána kudarc.” Ha egybeesik atries, parancsretryUntil.$maxExceptionsleállítás, ha a probléma ismételt kezeletlen kivételek miatt van.$timeouto--timeoutannak jelzésére, hogy egy Job hány másodpercig futhat, mielőtt a worker leállítja a gyermekfolyamatot.$failOnTimeoutidőtúllépés esetén a feladat sikertelenként való megjelölése.$backoffa módszerbackoff()annak meghatározására, hogy mennyi ideig kell várni az újrapróbálkozások között, még exponenciális értékek esetén is.
Ha egy feladat egy el nem fogott kivételt dob, a Laravel... visszaengedi a farokba amíg a beállított kísérletek száma el nem fogy. Ezt manuálisan vezérelheti a következővel: release($segundos) o fail($exception) amikor szándékosan sikertelenként szeretne megjelölni egy feladatot.
Sikertelen feladatok, failed_jobs tábla és metszés
Amikor egy Jób kimeríti erőfeszítéseit, akkor tekintik őt... sikertelen munka és a Laravel beszúrja a táblázatba failed_jobs (vagy a DynamoDB-ben, ha így konfigurálod). Ez a tábla tárolja az UUID-t, a kapcsolatot, a várólistát, a feladat hasznos adatait és a kiváltott kivételt.
Hasznos parancsok:
php artisan queue:failedhogy felsoroljam a sikerteleneket.php artisan queue:retry <id|all>hogy újra megpróbáljam őket.php artisan queue:forget <id>hogy töröljön egyet.php artisan queue:flushaz összes törléséhez (az újabb verziókban órákra vonatkozó opcióval).php artisan queue:prune-failed --hours=48a régi rekordok automatikus metszéséhez.
A Jobs részben definiálhatsz egy metódust failed(Throwable $exception) További tisztítási feladatokhoz: értesítse a felhasználót, vonjon vissza részleges műveleteket, írjon speciális naplókat stb. Vegye figyelembe, hogy a Job egy új példánya jön létre a híváshoz failed()Ezért ne hagyatkozzon a következő helyen végrehajtott ingatlanváltoztatásokra: handle().
Job batching: jobok kötegelése és azok kombinálása karakterláncokkal
Amikor több száz vagy több ezer kapcsolódó feladatot kell elindítani (például egy óriási CSV importálása darabokban, fájlok kötegelt feldolgozása, adatok tisztítása stb.), ajánlott a Laravel kötegelt funkcióját használni.
Alapfolyamat:
- hozza létre a táblázatot
job_batchesaphp artisan queue:batches-table && php artisan migrate. - Jelölje meg azokat a feladatokat, amelyek a tulajdonsággal rendelkező kötegek részét képezik majd
Batchable. - Használat
Bus::batch()egy sor Job küldése visszahívásokkalthen,catchyfinally. - Hozzáférés a köteghez minden egyes feladatból a következővel:
$this->batch()és ellenőrizd, hogy le van-e törölve. - Lehetőség további munkák hozzáadására egy folyamatban lévő köteghez
$this->batch()->add().
A kötegek (batch-ek) gyönyörűen integrálhatók a láncokkal : láncokat használhatsz egy kötegen belül, vagy kötegeket egy nagyobb lánc elemeiként. Ez különösen hasznos, ha több láncot szeretnél „párhuzamosan” futtatni, és valamit elindítani, amikor mindegyik befejeződött.
Munkavállalói végrehajtás, prioritások és telepítés
A sorok varázslata azért történik, mert van egy vagy több munkavállaló a parancs futtatása queue:work (o queue:listen(bár az utóbbi kevésbé hatékony). Ezek a folyamatok hosszú ideig futó démonok, amelyek figyelik a saját soraikat.
Főbb lehetőségek queue:work:
- Kapcsolat:
php artisan queue:work redis,queue:work databaseStb - Colas:
--queue=high,default,lowhogy rangsorolja. - -tizenegy: egyetlen feladatot dolgoz fel, majd kilép.
- –max-jobs: feldolgozza az X feladatot, majd leáll (a feldolgozók rendszeres újraindítása és a memória felszabadítása érdekében).
- –maximális idő: N másodpercig fut, majd kilép.
- -alvás: másodpercnyi várakozás, amikor nincsenek elérhető feladatok.
- –megáll-ha-üres: kiüríti a várólistát és tisztán lezár (ideális Docker környezetekben vagy egyszeri feladatokhoz).
- –időtúllépés: másodpercnyi időtúllépés feladatonként, ahogy azt korábban említettük.
- -erő: a feladatok feldolgozása akkor is, ha az alkalmazás karbantartási módban van.
Mivel ezek a folyamatok hosszú ideig futnak, éles környezetben szinte mindig egy folyamatfigyelőt , például a Supervisort (Linuxon) használnak az X munkafolyamatok elindítására, újraindításukra összeomlás esetén, valamint a naplók kezelésére. Egy tipikus Supervisor konfigurációs blokk Laravelhez a következőket határozza meg:
- parancs -vel a
php artisan queue:work ...Konkrét. - numprocs hogy jelezze, hány munkást kell párhuzamosan indítani.
- Naplózási útvonalak, felhasználók, automatikus újraindítások stb.
Sorok szüneteltetése és folytatása Laravelben
Térjünk át arra, ami gyakran fontos a karbantartás során: hogyan lehet szüneteltetni a sorban álló munkavállalókat anélkül, hogy hirtelen leállítanánk őket , és anélkül, hogy a feladatok befejezetlenek maradnának. A Laravel számos mechanizmust kínál, némelyik újabb, némelyik klasszikus, ennek szabályozására.
Szünet: sor:szünet és megszakítás jelek
A Laravel legújabb verzióiban speciális parancsokat ad hozzá a munkavállalók végrehajtásának szüneteltetéséhez és folytatásához :
php artisan queue:pause: azt jelzi a rendszernek, hogy ne vegyen fel új feladatokat, de hagyja a már folyamatban lévőket befejezni.php artisan queue:continue: az új feladatok feldolgozását onnan folytatja, ahol abbahagyta.
Ezek a parancsok úgy működnek, hogy jeleket küldenek a dolgozóknak a Laravel által belsőleg használt gyorsítótárazási mechanizmuson keresztül. Ezért fontos egy megfelelően konfigurált gyorsítótár-illesztőprogram (memcached, redis, database, file stb.), még akkor is, ha a tényleges gyorsítótár-várólista valami más.
Fontos: Egy sor vagy egy feldolgozó szüneteltetése nem szakítja meg vagy törli a már sorban álló feladatokat ; egyszerűen csak megakadályozza, hogy további feladatokat távolítsanak el a sorból a szüneteltetés ideje alatt.
A zavarok és a teljesítményre gyakorolt hatásuk felmérése
Minden alkalommal, amikor egy feldolgozó befejez egy feladatot, a Laravel ellenőrzi a gyorsítótárat újraindítás, szüneteltetés vagy folytatás jelek után . Ennek elhanyagolható költsége van, de létezik. Ha rendkívül a teljesítményre koncentrálsz, és tudod, hogy nem kell parancsokból szüneteltetned vagy újraindítanod a feldolgozókat, akkor letilthatod ezt a lekérdezést a következő hívással:
Queue::withoutInterruptionPolling();
Vagy akár statikus tulajdonságokat is módosíthat Illuminate\Queue\Worker bizonyos érintések letiltásához ($újraindítható, $szüneteltethetőAzonban, ha ezt megteszed, majd megpróbálod használni queue:pause o queue:restarta munkások Nem fogják megtudniEz egy olyan tervezési döntés, amit alaposan meg kell fontolni.
Manuális szüneteltetés a Supervisor vagy a Docker segítségével
A Laravel saját parancsain kívül éles környezetekben a folyamatok gyakran közvetve is „szünetelnek”:
- A program leállítása a Felügyelőben (
supervisorctl stop laravel-worker:*), ami megöli vagy megállítja a munkásokat. - használva –megáll-ha-üres a telepítésekben, hogy a dolgozók befejezhessék a sorban álló feladatokat, majd leállíthassák a rendszert.
- Dockerben a konténer feldolgozásának engedélyezése
--stop-when-emptyés aztán kikapcsol.
A különbség a queue:pause A folyamatok teljes leállításával a feladatok feldolgozása leáll, amíg a munkavégzők újra nem indulnak. belső szünet A folyamatokat a memóriában tarthatja, és a parancsra várhat. continueEz hasznos gyors visszaállítási telepítésekhez vagy rövid karbantartási időszakokhoz.
Adatbázis tranzakciók és after_commit
Klasszikus hiba: a feladatok adatbázis- tranzakciókon belüli kiküldése. Ha nem vigyázunk, a worker végrehajthatja a feladatot a commit előtt, és a várt modell vagy adat még nem is szerepelhet az adatbázisban.
Ennek a táncnak az elkerülésére két lehetőséged van:
- Aktiválása
'after_commit' => truea várólista-kapcsolat konfigurációjában. Így egy tranzakción belül kiküldött minden Job belsőleg elhalasztásra kerül a jóváhagyásáig. - Feladatonkénti módszerek használata
afterCommit()obeforeCommit()diszpécserkedéskor, hogy a viselkedést csak bizonyos Jobokban kényszerítse ki.
Ha a tranzakciót megfordítják, a közben kiküldött feladatok elvetik őket anélkül, hogy valaha is bekerülnének a sorba, ami pontosan az, amire általában szükség van a konzisztencia fenntartásához.
Monitorozás, sorkiürítés és tesztelés
Ha már működőképesek a várólisták, nem elég csak kidobni a Jobs feladatokat és elfelejteni az egészet; figyelni és tesztelni kell , hogy minden hogyan viselkedik.
Hasznos eszközök és parancsok:
queue:clearegy adott sor kiürítéséhez (SQS, Redis, adatbázis).queue:monitorbizonyos várólistákban lévő feladatok számának figyelése és az esemény kiváltásaQueueBusyha túllépnek egy küszöbértéket.- Állásesemények mint
Queue::before,Queue::after,Queue::loopingyQueue::failingegyéni logika összekapcsolásához (naplók, metrikák, visszagörgetések stb.). - Hamisítványok a tesztelésben használatával
Queue::fake()yBus::fake()annak ellenőrzésére, hogy a Jobok, karakterláncok vagy kötegek elküldésre kerültek-e anélkül, hogy ténylegesen végrehajtották volna őket.
A tesztekben olyan kijelentések lehetségesek, mint például, hogy „ez a feladat X alkalommal került sorra” , „egy ilyen feladatokat tartalmazó lánc ebben a sorrendben lett elküldve” vagy „egyetlen konkrét feladat sem került sorra”, ami nagy biztonságot nyújt összetett folyamatokban.
Ezzel a teljes ökoszisztémával – olyan meghajtóprogramokkal, mint a Redis vagy az SQS, jól megtervezett feladatokkal, finomhangoláshoz szükséges köztes szoftverekkel, kötegekkel, láncokkal, újrapróbálkozási konfigurációval, felügyelő által kezelt munkafolyamatokkal és olyan parancsokkal, mint a queue:pause y queue:continue— A Laravel segítségével milliméter pontossággal uralhatod a háttérben zajló feldolgozást, a tipikus e-mail-küldéstől az elosztott, feladatátvételt biztosító sorarchitektúrákig, biztosítva, hogy az alkalmazásod továbbra is gyorsan reagáljon a HTTP rétegen, miközben alatta nehéz munka folyik, anélkül, hogy blokkolnád a felhasználót.