- Laravel piedāvā vienotu rindu API ar vairākiem draiveriem (datubāze, Redis, SQS…) un atdalīšanu starp savienojumiem un loģiskajām rindām.
- Darbi ļauj pārvietot sarežģītus uzdevumus uz fonu, nodrošinot atbalstu modeļu serializēšanai, starpprogrammatūrai, vienreizējiem darbiem, šifrēšanai, partijām un virknēm.
- Darbinieki tiek pārvaldīti ar queue:work, Supervisor un tādām komandām kā queue:pause/queue:continue, kontrolējot atkārtotus mēģinājumus, taimautus un prioritātes.
- Ir pilnīga kļūmju, uzraudzības un testēšanas ekosistēma (failed_jobs, queue:retry, queue:monitor, Queue::fake), kas padara rindas uzticamas ražošanas vidē.

Darbs ar rindām Laravel vidē ir gandrīz obligāts jebkurā puslīdz nopietnā projektā: e-pastu sūtīšana, CSV failu apstrāde, PDF failu ģenerēšana, attēlu izmēru maiņa, ārējo API izsaukšana… Ja tas viss tiek darīts galvenajā HTTP pieprasījumā, vietne kļūst lēna, parādās 500 kļūdas, un lietotājs galu galā izmisīgi skatās tukšā ekrānā.
Labā ziņa ir tā, ka Laravel piedāvā jaudīgu un elastīgu rindu veidošanas infrastruktūru , kas ļauj deleģēt lielu slodzi fona procesiem, pārvaldīt tos pēc prioritātes, grupēt partijās, uzraudzīt, mēģināt atkārtoti, ja tie neizdodas, un pat īslaicīgi apturēt darbiniekus apkopes veikšanai. Aplūkosim tuvāk (un neko neizlaidīsim garām), kā to maksimāli izmantot, tostarp kā apturēt, atsākt un kontrolēt tās darbību ražošanas vidē.
Pamatjēdzieni: savienojumi, rindas un draiveri
Laravel vidē, pirms jebkādu darbību apturēšanas, ir jāsaprot atšķirība starp rindu savienojumi un pašas rindas. uz config/queue.php jums ir masīvs connections kur jūs definējat katru aizmugures sistēmu: datubāze, redis, beanstalkd, sqs, sinhronizācija, null, dublēšana, rabbitmq (ja to pievienojat) utt.
Katram savienojumam var būt vairāki loģiskās rindas (vārdi, piemēram, default, emails, high, low, importsAtribūts queue Katrs savienojums norāda, kura ir noklusējuma rinda, kurā tiks ievietoti darbi, ja nav norādīts cits. onQueue()Tādā veidā jūs varat veikt šādas darbības:
- Ātra rinda e-pastiem vai īsiem darījumiem.
- Vēl viena zema prioritāte ilgstošiem uzdevumiem, piemēram, video vai lielu pārskatu apstrādei.
- Rindas segmentētas pēc uzdevuma veida:
imports,notificaciones,reportes, Uc
Kad jūs palaižat darbinieku ar php artisan queue:workPēc noklusējuma tas klausās rindu, kas norādīta kā noklusējums atlasītajā savienojumā. Ja vēlaties noteikt prioritāti, varat nodot vairākas ar komatiem atdalītas rindas:
php artisan queue:work redis --queue=high,default,low
Tādā veidā darbinieks vispirms apstrādā high (augstas prioritātes) , tad default (noklusējuma prioritātes) un tikai tad low (zemas prioritātes) , kas ir ļoti svarīgi, kad sistēma ir ielādēta un jūs nevēlaties, lai 30 minūšu atskaite bloķētu augstas prioritātes e-pastus.
Rindu vadītāji un priekšnosacījumi
Laravel piedāvā vienotu API vairākiem rindu draiveriem , taču katram no tiem ir savas specifiskās funkcijas un atkarības. Pirms darbinieku pauzēšana ir ļoti svarīgi izvēlēties pareizo draiveri.
Vadītāju datubāze
Šoferis datubāze Tas uzglabā darbus SQL tabulā (parasti jobsTo ir viegli uzstādīt, un tas ir lieliski piemērots maziem projektiem vai izstrādes vidēm, kurās nevēlaties ņemties ar Redis vai SQS.
Pamatdarbības:
- Ģenerēt migrāciju:
php artisan queue:table(vai jaunākās versijās tas ir šādscreate_jobs_tablenoklusējuma). - Veikt migrācijas:
php artisan migrate. - Konfigurēt QUEUE_CONNECTION=datubāze kas
.envun apstiprinietconfig/queue.phpka'default' => env('QUEUE_CONNECTION','database').
Tas ir ērti un pietiekami stabili, taču daudzu rindu un lielas datplūsmas dēļ tas var kļūt par sašaurinājumu , jo viss notiek caur vienu un to pašu relāciju datubāzi.
Vadītājs Redis
Redis draiveris ir standarta darba zirgs ražošanas vidē. Tas ir ātrs, atbalsta uzlabotas funkcijas (bloķēšanu, ātruma ierobežošanu, atomu bloķēšanu, Horizon utt.) un ļoti labi mērogojams.
Svarīgi punkti:
- Jums ir jākonfigurē Redis savienojums
config/database.php. - Iespējas
serializerycompressionno Redis Tie nav saderīgi ar rindas vadītāju. - Ja lietojat Redis klasterisRindu nosaukumiem jābūt ar jaucējtagu, piemēram
{default}lai visas atslēgas šajā rindā nonāktu vienā un tajā pašā slotā. - Iespēja
block_forTas ļauj darbiniekam bloķēt, dažas sekundes gaidot uzdevumus, nevis nepārtraukti aptaujāt: ietaupa procesora un samazina vaicājumu skaitu Redis serverim.
Piemēram:
'redis' => ,
Ja jūs ievietojat bloķēšanas_priekšmets = 0Darbinieks paliek bloķēts uz nenoteiktu laiku, līdz kļūst pieejams darbs, kas jāpatur prātā, ja vēlaties, lai tas ātri reaģētu uz tādiem signāliem kā SIGTERM vai pauzes komandas.
Citi draiveri: SQS, Beanstalkd, null, dublēšana…
Papildus datubāzēm un redis, Laravel atbalsta arī citas sistēmas :
- Amazon SQSPārvaldītas rindas pakalpojumā AWS ar atbalstu FIFOZiņojumu grupas, deduplikācija un papildu redzamības iestatījumi. Nepieciešams SDK.
aws/aws-sdk-php. - BeanstalkdĻoti ātri un vienkārši, izmantojot iepakojumu
pda/pheanstalk. - sinhronizēt: veic uzdevumus nekavējoties tajā pašā procesā. Noderīgi izstrādē vai testēšanā, bet ražošanas vidē tas praktiski ir tas pats, kas neizmantot rindas vispār.
- nulle: Atmet uzdevumus, tiklīdz tie ir "nosūtīti". Izmanto, lai pilnībā atspējotu rindu sistēmu.
- kļūmjpārlēceTas ļauj konfigurēt vairākus savienojumus, un, ja primārais neizdodas, Laravel mēģina pārsūtīt uzdevumu uz nākamo sarakstā. Lieliski piemērots vidēm, kur augsta pieejamība ir kritisks.
Darbinieku pauzēšana un atsākšana praktiski notiek vienādi neatkarīgi no draivera, jo to pārvalda Artisan komandas un Worker klase , nevis rindas aizmugursistēma.
Darba izveide un modeļa serializācija
Un Darbs Laravel valodā tā ir vienkārši klase, kas ietver uzdevumu, kas jāizpilda rindā. Tā parasti tiek ģenerēta ar Artisan un saglabāta mapē app/Jobs.
Lai to izveidotu:
php artisan make:job ProcessPodcast
Ģenerētā klase īsteno ShouldQueue un parasti izmanto īpašības Dispatchable, InteractsWithQueue, Queueable y SerializesModelsSirds slēpjas metodē handle()ko darbinieks dara, kad darbs pienāk.
Īpaši jaudīga funkcija ir Eloquent modeļu automātiskā serializācija . Ja Job konstruktorā akceptējat modeli, Laravel nepievieno rindai visu objektu, tikai tā identifikatoru. Kad uzdevums tiek apstrādāts, tas rekonstruē modeli no datubāzes ar ielādētām relācijām.
Tipisks piemērs (pseidokodā, lai izvairītos no burtiskas atkārtošanas):
- Būvnieks saņem Podkāsts $podkāsts.
- Īpašība
SerializesModelsTā ir atbildīga par ID saglabāšanu. - En
handle(AudioProcessor $processor)Jūs veicat smago darbu (piemēram, apstrādājat audio).
Ja nevēlaties, lai modeļa attiecības tiktu serializētas (lai lietderīgā slodze nebūtu milzīga), varat izmantot $model->withoutRelations() vai PHP 8 atribūts # uz īpašumu, ko reklamē celtnieks.
Atkarību injekcija roktura metodē
Vēl viena priekšrocība ir tā, ka jūs varat injicēt pakalpojumus tieši roktura metodē (it kā tas būtu kontrolieris), jo Laravel arī izmanto pakalpojumu konteineru Jobs. Piemēram, jūs varat pieprasīt AudioProcessorHTTP klienti, repozitoriji utt., un sistēma rūpējas par to risināšanu.
Ja jums ir nepieciešama īpaši precīza tā sauktā handlejūs varat izmantot Container::bindMethod() pakalpojumu sniedzējā un pats definējiet injekcijas loģiku, taču vairumā gadījumu nav nepieciešams lietas tik ļoti sarežģīt.
Darba starpprogrammatūra
Tāpat kā maršrutiem ir starpprogrammatūra, arī darbiem var būt specifiska starpprogrammatūra kas darbojas pirms un pēc uzdevuma. Tas ievērojami samazina atkārtotu kodu metodēs handle() un tas ir īpaši noderīgi:
- Ātruma ierobežošana ar Redisu.
- izvairīties pārklājas darbu, kas skar vienu un to pašu resursu.
- Regulāri izņēmumi nestabilām API.
- Uzdevumu izlaišana noteiktos apstākļos (
Skipstarpprogrammatūra).
Starpprogrammatūra parasti tiek ievietota app/Jobs/Middleware un tiek atgriezti no metodes middleware() No Ījaba grāmatas. Konceptuāls piemērs:
public function middleware(): array { return ;
Īpaši darba veidi: unikāli, šifrēti un bloķēti
Laravel ļauj atzīmēt noteiktus darbus kā unikāls lai nodrošinātu, ka rindā vienlaikus netiek ievietotas divas identiskas instances. Tas tiek panākts, ieviešot saskarni ShouldBeUnique o ShouldBeUniqueUntilProcessingun atbalsta atslēgas definēšanu uniqueId() un laiks uniqueFor.
Tas ir ideāli piemērots tādām lietām kā:
- Pārrēķināt produkta meklēšanas indeksu: tikai vienu reizi katram produktam līdz tas beigsies.
- Sinhronizācija ar ārējiem pakalpojumiem, kas neļauj vienlaicīgi pieprasīt vienu un to pašu resursu.
Zemāk Laravel izmanto atomu slēdzene kešatmiņas (Redis, memcached, datubāze utt.). Varat arī izvēlēties kešatmiņas draiveri šai bloķēšanai ar uniqueVia().
Turklāt ir arī saskarne ShouldBeEncrypted, ar kuru jūs norādāt, ka viss Darbs ir pabeigts Ievadiet savu kodu pirms ieiešanas rindāĻoti noderīgi, pārsūtot sensitīvus datus, un nevēlaties, lai tie ceļotu vienkāršā tekstā caur Redis, SQS vai datubāzi.
Nosūtīt, atlikt un izpildīt uzdevumus dažādos režīmos
Kad jūsu uzdevums ir definēts, jūs to palaižat ar Job::dispatch() no kontrolieriem, notikumu klausītājiem, Artisan komandām vai pat slēgumiem. Parametri, ko jūs nododat dispatch Viņi dodas tieši pie Ījaba cēlāja.
Interesantas variācijas:
dispatchIf()ydispatchUnless()kondicionēt sūtījumu vienā līnijā.delay()lai uzdevumu nevarētu apstrādāt līdz noteiktam datumam/laikam.dispatchAfterResponse()oafterResponse()endispatch()Slēgšanas, kas atliek izpildi, līdz ir nosūtīta HTTP atbilde, bet tā paša PHP procesa ietvaros.dispatchSync()lai uzdevumu palaistu sinhroni (neiziet cauri rindai), bet atkārtoti izmantojot to pašu klasi.- Īpaši savienojumi, piemēram,
deferredobackgroundlai izpildītu pēc atbildes, tajā pašā procesā vai jaunā PHP procesā.
Visbeidzot, savienojumu un rindu var norādīt ar ķēdē savienotām metodēm. onConnection() y onQueue(), vai nu nosūtīšanas laikā, vai darbu veidotājā.
Precīza kontrole: atkārtoti mēģinājumi, atlikšana, taimauti un kļūdu apstrāde
Liela daļa no darba ar rindām Laravel vidē ir izlemt, cik reižu atkārtot uzdevumu , cik ilgi gaidīt starp mēģinājumiem un kad to uzskatīt par kļūmi.
Pieejamās iespējas:
--triesenqueue:worklai iestatītu maksimālo mēģinājumu skaitu visiem šī darbinieka darbiem (ja vien darbs pats nedefinē savu)$triesotries()).$triesvai metodetries()Job klasē katrai Job kontrolei.retryUntil()teikt: “mēģiniet vēlreiz, kā vēlaties, līdz šim brīdim, pēc tam neveiksme.” Ja tas sakrīt artries, komandaretryUntil.$maxExceptionslai pārtrauktu darbību, ja problēma rodas atkārtotu neapstrādātu izņēmumu dēļ.$timeouto--timeoutlai norādītu, cik sekundes darbs var darboties, pirms darbinieks iznīcina bērna procesu.$failOnTimeoutlai taimauta gadījumā atzīmētu uzdevumu kā neizdevušos.$backoffmetodebackoff()lai definētu, cik ilgi jāgaida starp atkārtotiem mēģinājumiem, pat ar eksponenciālām vērtībām.
Ja uzdevums izmet nekonstatētu izņēmumu, Laravel to darīs... izlaiž atpakaļ astē līdz konfigurētie mēģinājumi ir izsmelti. To var kontrolēt manuāli, izmantojot release($segundos) o fail($exception) ja vēlaties apzināti atzīmēt darbu kā neizdevušos.
Neizdevušies darbi, failed_jobs tabula un atzarošana
Kad Ījabs ir izsmēlis visus savus centienus, viņu sāk uzskatīt par neveiksmīgs darbs un Laravel to ievieto tabulā failed_jobs (vai DynamoDB, ja to konfigurējat šādi). Šajā tabulā ir saglabāta UUID, savienojums, rinda, darba slodze un izmests izņēmums.
Noderīgas komandas:
php artisan queue:failedlai uzskaitītu neveiksmīgos.php artisan queue:retry <id|all>lai mēģinātu tos vēlreiz.php artisan queue:forget <id>lai vienu izdzēstu.php artisan queue:flushlai dzēstu visu (ar iespēju dzēst stundas jaunākās versijās).php artisan queue:prune-failed --hours=48lai automātiski apgrieztu vecos ierakstus.
Darbu sadaļā var definēt metodi. failed(Throwable $exception) Papildu tīrīšanai: paziņojiet lietotājam, atsauciet daļējas darbības, rakstiet specializētus žurnālus utt. Ņemiet vērā, ka tiek izveidots jauns Job eksemplārs, lai izsauktu failed()Tāpēc nepaļaujieties uz īpašuma izmaiņām, kas veiktas handle().
Darbu partiju apstrāde: darbu partijas un to apvienošana ar virknēm
Kad nepieciešams palaist simtiem vai tūkstošiem saistītu uzdevumu (piemēram, importēt milzīgu CSV failu pa daļām, apstrādāt failus partijās, tīrīt datus utt.), ieteicams izmantot Laravel partiju apstrādes funkcionalitāti .
Pamata plūsma:
- izveidot tabulu
job_batchesarphp artisan queue:batches-table && php artisan migrate. - Atzīmējiet darbus, kas būs daļa no partijām ar pazīmi
Batchable. - Izmantot
Bus::batch()nosūtīt uzdevumu komplektu ar atzvanīšanas pieprasījumiemthen,catchyfinally. - Piekļūstiet katra darba partijai ar
$this->batch()un pārbaudiet, vai tas ir atcelts. - Iespēja pievienot vēl citus darbus notiekošajai partijai ar
$this->batch()->add().
Partijas lieliski integrējas ar ķēdēm : ķēdes var būt vienas partijas ietvaros vai partijas var būt lielākas ķēdes elementi. Tas ir īpaši noderīgi, ja vēlaties, lai vairākas ķēdes darbotos "paralēli" un aktivizētu kaut ko, kad tās visas ir pabeigtas.
Darbinieku izpilde, prioritātes un izvietošana
Visa rindu maģija rodas tāpēc, ka jums ir viens vai vairāki darbinieki palaižot komandu queue:work (o queue:listen(lai gan pēdējais ir mazāk efektīvs). Šie procesi ir ilgstoši darbojošies dēmoni, kas klausās savas attiecīgās rindas.
Galvenās iespējas queue:work:
- Savienošana:
php artisan queue:work redis,queue:work database, Uc - Colas:
--queue=high,default,lownoteikt prioritātes. - -vienpadsmit: apstrādā vienu uzdevumu un iziet no tā.
- –maksimālie darbi: apstrādā X uzdevumus un pārtrauc darbību (lai periodiski restartētu darbiniekus un atbrīvotu atmiņu).
- –maksimālais laiks: apstrādā N sekundes un pēc tam iziet.
- –miegs: gaidīšanas sekundes, ja nav pieejamu darbu.
- –apstāties, kad tukšs: iztukšo rindu un tīri aizveras (ideāli piemērots Docker vidēm vai vienreizējiem darbiem).
- –taimauts: taimauta sekundes katram uzdevumam, kā jau minējām iepriekš.
- - spēku: apstrādāt uzdevumus pat tad, ja lietotne ir apkopes režīmā.
Tā kā šie procesi darbojas ilgstoši, ražošanas vidē X darbinieku palaišanai, to restartēšanai avārijas gadījumā un žurnālu pārvaldībai gandrīz vienmēr tiek izmantots procesu monitors, piemēram, Supervisor (operētājsistēmā Linux). Tipisks Supervisor konfigurācijas bloks Laravel definē:
- komanda ar
php artisan queue:work ...betons. - numprocs lai norādītu, cik darbinieku paralēli palaist.
- Žurnālu ceļi, lietotājs, automātiskā restartēšana utt.
Rindu apturēšana un atsākšana programmā Laravel
Pievērsīsimies tam, kas bieži vien ir svarīgi apkopē: kā apturēt rindas darbiniekus, tos pēkšņi neapturot un neatstājot darbus nepabeigtus. Laravel piedāvā vairākus mehānismus, dažus jaunākus, dažus klasiskus, lai to kontrolētu.
Pauze: rinda:pauze un pārtraukuma signāli
Jaunākajās versijās Laravel pievieno īpašas komandas, lai apturētu un atsāktu darbinieku izpildi :
php artisan queue:pause: norāda sistēmai pārtraukt jaunu uzdevumu uzņemšanos, bet ļaut pabeigt jau iesāktos uzdevumus.php artisan queue:continue: atsāk jaunu uzdevumu apstrādi no vietas, kur tie tika pārtraukti.
Šīs komandas darbojas, nosūtot signālus darbiniekiem, izmantojot kešatmiņas mehānismu, ko Laravel izmanto iekšēji. Tāpēc ir svarīgi, lai būtu pareizi konfigurēts kešatmiņas draiveris (memcached, redis, database, file utt.), pat ja jūsu faktiskā kešatmiņas rinda ir kaut kas cits.
Svarīgi: Rindas vai darbinieka apturēšana neatceļ un neizdzēš rindā jau esošos darbus ; tā vienkārši neļauj noņemt citus darbus no rindas pauzes laikā.
Traucējumu un to ietekmes uz veiktspēju aptauja
Katru reizi, kad darbinieks pabeidz darbu, Laravel pārbauda kešatmiņu, lai atrastu restartēšanas, pauzes vai turpināšanas signālus . Tam ir niecīgas izmaksas, taču tas pastāv. Ja jūs esat ārkārtīgi koncentrējies uz veiktspēju un zināt, ka jums nebūs jāaptur vai jārestartē darbinieki no komandām, varat atspējot šo aptauju, izsaucot:
Queue::withoutInterruptionPolling();
Vai pat pielāgot statiskās īpašības Illuminate\Queue\Worker lai atspējotu noteiktus pieskārienus ($restartējams, $pauzējamsTomēr, ja jūs to darāt un pēc tam mēģināt izmantot queue:pause o queue:restartstrādnieki Viņi to neuzzināsTas ir dizaina lēmums, kas rūpīgi jāapsver.
Manuāla pauze, izmantojot Supervisor vai Docker
Papildus Laravel komandām , ražošanas vidē procesi bieži tiek "apturēti" netieši:
- Programmas apturēšana sadaļā “Supervisor” (
supervisorctl stop laravel-worker:*), kas nogalina vai aptur strādniekus. - Izmantojot –apstāties, kad tukšs izvietojumos, lai darbinieki varētu pabeigt rindā esošos darbus un pēc tam pārtraukt darbu.
- Dockerā ļaujot konteineram apstrādāt
--stop-when-emptyun tad tas izslēdzas.
Atšķirība ar queue:pause Pilnībā apturot procesus, jūs pārtrauksiet darbu apstrādi, līdz darbinieki restartēsies. iekšēja pauze Jūs varat saglabāt procesus atmiņā, gaidot komandu continueTas ir noderīgi ātrai atcelšanas izvietošanai vai īsiem apkopes periodiem.
Datu bāzes transakcijas un after_commit
Klasiska kļūda: uzdevumu nosūtīšana datubāzes transakciju ietvaros. Ja neesat uzmanīgs, darbinieks var izpildīt uzdevumu pirms apstiprinājuma veikšanas, un gaidītais modelis vai dati, iespējams, vēl nav datubāzē.
Lai izvairītos no šīs dejas, jums ir divas iespējas:
- Aktivizēt
'after_commit' => truerindas savienojuma konfigurācijā. Tādējādi jebkurš darījuma ietvaros nosūtītais uzdevums (Job) tiek iekšēji atlikts, līdz tas tiek apstiprināts. - Izmantojiet metodes katram uzdevumam atsevišķi
afterCommit()obeforeCommit()nosūtot, lai piespiestu darbību tikai noteiktos darbos.
Ja transakcija tiek atcelta, tās laikā nosūtītie darbi tiek atmesti, nekad nenonākot rindā, kas parasti ir tieši tas, kas ir nepieciešams, lai saglabātu konsekvenci.
Uzraudzība, rindu tīrīšana un testēšana
Kad rindas ir izveidotas un darbojas nopietni, nepietiek vienkārši atmest Darbus un aizmirst par to; jums vajadzētu uzraudzīt un pārbaudīt, kā viss darbojas.
Noderīgi rīki un komandas:
queue:clearlai iztukšotu noteiktu rindu (SQS, Redis, datubāze).queue:monitorlai uzraudzītu uzdevumu skaitu noteiktās rindās un aktivizētu notikumuQueueBusyja tie pārsniedz noteiktu slieksni.- Darba pasākumi kā
Queue::before,Queue::after,Queue::loopingyQueue::failinglai piesaistītu pielāgotu loģiku (žurnālus, metrikas, atcelšanas utt.). - Viltojumi testēšanā izmantojot
Queue::fake()yBus::fake()lai pārbaudītu, vai darbi, virknes vai partijas ir nosūtītas, tās faktiski neizpildot.
Testos var norādīt tādus apgalvojumus kā “šis uzdevums ir ievietots rindā X reizes” , “ķēde ar šiem uzdevumiem ir nosūtīta šādā secībā” vai “neviens konkrēts uzdevums nav ievietots rindā”, kas nodrošina lielu drošību sarežģītās plūsmās.
Ar visu šo ekosistēmu — draiveriem, piemēram, Redis vai SQS, labi izstrādātiem darbiem, starpprogrammatūru precīzai noregulēšanai, partijām, ķēdēm, atkārtotas mēģinājumu konfigurāciju, vadītāja pārvaldītiem darbiniekiem un komandām, piemēram, queue:pause y queue:continue— Laravel ļauj apgūt fona apstrādi līdz milimetram, sākot no tipiskas e-pasta sūtīšanas līdz izkliedētām rindu arhitektūrām ar dublēšanas funkciju, nodrošinot, ka jūsu lietojumprogramma turpina ātri reaģēt HTTP slānī, kamēr zem tā tiek veikts intensīvs darbs, nebloķējot lietotāju.