Utsettelsesoppgaver i Laravel ved hjelp av køer

I denne artikkelen skal vi utforske Queue API i Laravel web-rammeverket. Den lar deg utsette ressursintensive oppgaver under utførelse av manus for å forbedre den totale sluttbrukeropplevelsen. Etter å ha introdusert grunnleggende terminologi, demonstrerer jeg det ved å implementere et ekteeksempel.

Sidetilpasningstid er et viktig aspekt av ethvert vellykket nettsted, og man bør ikke overse betydningen av det da det påvirker SEO av nettstedet og den generelle sluttbrukeropplevelsen også. Oftere enn ikke, må du ende opp med å feilsøke nettsider med langsidetider. Selvfølgelig er det forskjellige tilnærminger du kan bruke til å rette opp dette problemet.

Ved etterforskning innser du ofte at det er visse kodeblokker som forårsaker en forsinkelse i sideutførelsen. Det neste du kan prøve, er å identifisere blokker som kan utsettes for behandling, og som ikke har noen reell innvirkning på sluttresultatet for gjeldende side. Det bør virkelig forbedre den totale nettsiden hastighet som vi har eliminert kodeblokker som forårsaket en forsinkelse.

I dag skal vi utforske et lignende konsept i sammenheng med Laravel web-rammeverket. Faktisk gir Laravel allerede en nyttig innebygd API som gjør at vi kan utsette behandlingen av oppgaver, Queue API. Uten å kaste bort mye av tiden din, vil jeg gå videre og diskutere de grunnleggende elementene i kø-API.

Drivere, tilkoblinger, køer og jobber

Det grunnleggende formålet med kø-API er å kjøre jobber som legges til i køen. Deretter kan køen tilhøre en bestemt tilkobling, og den forbindelsen kan tilhøre en bestemt kødriver som er konfigurert med selve forbindelsen. La oss kort prøve å forstå hva jeg nettopp har sagt.

Kø-drivere

På samme måte som du ville ha brukt en annen driver for databasetilkoblingen, kan du også velge mellom en rekke forskjellige kødrivere. Que-APIen støtter forskjellige adaptere som database, beanstalkd, sqs og redis.

Kødriveren er bare et sted som brukes til å lagre kørelatert informasjon. Så hvis du bruker en database kø driver, for eksempel, vil den nye jobben bli lagt til i jobben tabellen i databasen. På den annen side, hvis du har konfigurert redis som standard kødriver, legges jobben til redis-serveren.

Que-API-en gir også to spesielle kø-drivere for testformål-synkronisering og null. Synkroniseringskøen driveren brukes til å utføre en kø jobb umiddelbart, mens nullkø driveren brukes til å hoppe over en jobb slik at den ikke vil bli fullført i det hele tatt.

tilkoblinger

Når du konfigurerer kø-API for første gang, må du angi en standardforbindelse som skal brukes til standard købehandling. I det minste forventes forbindelsen å gi følgende informasjon:

  • kødriveren som vil bli brukt
  • kødriverens spesifikke konfigurasjonsverdier
  • standard kø navnet der jobben vil bli lagt til

køer

Når du legger til en jobb i en kø, blir den lagt til i standardkøen. Faktisk, det burde være bra i de fleste tilfeller, med mindre du har jobber som må gis høyere prioritet enn andre jobber. I så fall kan du opprette en kø som heter høy og plasser jobber med høyere prioritet i den aktuelle køen.

Når du kjører en køarbeider som behandler jobber i kø, kan du eventuelt passere --kø parameter, som lar deg oppgi kønavn i den rekkefølgen de må behandles i. For eksempel, hvis du spesifiserer --køen = høy, standard, Det vil først behandle jobber i høy kø, og når den er fullført, henter den jobber i standardkøen.

Arbeidsplasser

En jobb i kø-APIen er en oppgave som er utsatt for hovedkjøpsflyten. Hvis du for eksempel vil opprette en miniatyrbilde når brukeren laster opp et bilde fra forkant, kan du opprette en ny jobb som håndterer miniatyrprosessen. På denne måten kan du utsette oppgaven med miniatyrbehandling fra hovedkjøpsflyten.

Det var en grunnleggende introduksjon til kø-API-terminologien. Fra neste avsnitt og utover, vil vi undersøke hvordan du lager en tilpasset køjobb og kjører den ved hjelp av en Laravel køarbeider.

Lag din første køjobb

Nå skal du føle deg trygg på køen jobber. Fra dette avsnittet fortsetter vi å implementere et ekteeksempel som demonstrerer konseptet med køarbeider i Laravel.

Oftere enn ikke, ender du opp i situasjonen der du må opprette forskjellige miniatyrversjoner av et bilde lastet opp av en bruker. I de fleste tilfeller forsøker utvikleren å behandle det i sanntid, slik at forskjellige versjoner av bilder blir opprettet med en gang når brukeren laster opp et bilde.

Det ser ut til å være en rimelig tilnærming hvis du skal lage et par versjoner, og det tar ikke for mye tid i utgangspunktet. På den annen side, hvis du har å gjøre med et program som krever tung behandling, og dermed spiser flere ressurser, kan sanntidsbehandling ende opp med en dårlig brukeropplevelse..

Det opplagte alternativet som dukker opp i første omgang, er å utsette behandlingen av miniatyrbildet så sent som mulig. Den enkleste tilnærmingen du kan implementere i dette spesifikke scenariet er å sette en cron-jobb som utløser behandling med jevne mellomrom, og du burde ha det bra.

En mye bedre tilnærming er derimot å utsette og presse oppgaven inn i en kø, og la køarbehandleren behandle det når det blir en sjanse til å gjøre det. I et produksjonsmiljø er køarbehandleren et demonstrasjonsskript som alltid kjører og behandler oppgaver i en kø. Den åpenbare fordelen med denne tilnærmingen er en mye bedre sluttbrukeropplevelse, og du trenger ikke vente på cron-løp da jobben blir behandlet så snart som mulig.

Jeg antar det er nok teori for å komme i gang med en faktisk implementering.

I vårt tilfelle skal vi bruke database kødriver, og det krever at vi oppretter arbeidsplasser tabell i databasen. De arbeidsplasser Tabellen inneholder alle jobbene som må behandles i neste køarbeiderløp.

Før vi går videre og oppretter arbeidsplasser tabell, la oss endre standard køkonfigurasjonen fra synkron til database i config / queue.php fil.

... / * | ---------------------------------------------- ---------------------------- | Standard kø driver | ---------------------------------------------- ---------------------------- | | Laravel's kø API støtter et utvalg av bakender via en enkelt | API, noe som gir deg enkel tilgang til hver back-end med samme | syntaks for hver enkelt. Her kan du angi standard kø-driveren. | | Støttes: "synkronisering", "database", "beanstalkd", "sqs", "redis", "null" | * / 'default' => env ('QUEUE_DRIVER', 'database'), ... 

Faktisk gir Laravel allerede en håndverkskommando som hjelper oss å skape arbeidsplasser bord. Kjør følgende kommando i roten til Laravel-programmet, og den skal skape den nødvendige databasemigrasjonen som skaper arbeidsplasser bord.

$ php håndverkskø: bord

Migreringsfilen som genereres på database / vandringer / YYYY_MM_DD_HHMMSS_create_jobs_table.php skal se slik ut:

bigIncrements ( 'id'); $ Bord-> streng ( 'køen'); $ Tabell-> longText ( 'nyttelast'); $ Tabell-> unsignedTinyInteger ( 'forsøk'); $ Tabell-> unsignedInteger ( 'reserved_at') -> ha nullverdier (); $ Tabell-> unsignedInteger ( 'available_at'); $ Tabell-> unsignedInteger ( 'created_at'); $ table-> index (['kø', 'reserved_at']); );  / ** * Omvendt migrasjonene. * * @return void * / offentlig funksjon ned () Schema :: dropIfExists ('jobs');  

Neste, la oss kjøre migrere kommandoen slik at den faktisk skaper arbeidsplasser bord i en database.

php artisan migrere

Det er så langt som arbeidsplasser migrasjon er opptatt.

Neste, la oss lage Bilde modell som vil bli brukt til å håndtere bilder lastet opp av sluttbrukeren. Bildemodellen krever også en tilhørende database tabell, så vi skal bruke --migrere alternativet mens du oppretter Bilde modell.

php artisan make: modell Image - migrasjon

Kommandoen ovenfor skal opprette Bilde modell klasse og en tilhørende database migrasjon også.

De Bilde modellklassen skal se slik ut:

Og databasen migreringsfilen skal opprettes på database / vandringer / YYYY_MM_DD_HHMMSS_create_images_table.php. Vi vil også lagre den opprinnelige banen til bildet lastet opp av sluttbrukeren. La oss revidere koden til Bilde database migreringsfil for å se ut som følgende.

trinn ( 'id'); $ Tabell-> tidsstempler (); $ Bord-> streng ( 'org_path'); );  / ** * Omvendt migrasjonene. * * @return void * / offentlig funksjon ned () Schema :: dropIfExists ('images'); 

Som du kan se, har vi lagt til $ Tabell-> string ( 'org_path') kolonne for å lagre banen til det opprinnelige bildet. Deretter trenger du bare å kjøre migrere kommandoen for å faktisk opprette det tabellen i databasen.

$ php håndverk migrere

Og det er det så langt som Bilde modellen er bekymret.

Deretter la vi opprette en faktisk køjobb som er ansvarlig for å behandle bildeminiatyrer. For miniatyrprosessen skal vi bruke et meget populært bildebehandlingsbibliotek-intervensjonsbilde.

For å installere Interventions Image-biblioteket, fortsett og kjør følgende kommando i roten til søknaden din.

$ php composer.phar krever intervensjon / bilde

Nå er det på tide å lage Jobb klassen, og vi vil bruke en artisan kommando for å gjøre det.

$ php artisan make: jobb ProcessImageThumbnails

Det burde skape Jobb klassemaler på app / Jobb / ProcessImageThumbnails.php. La oss erstatte innholdet til den filen med følgende.

image = $ image;  / ** * Utfør jobben. * * @return void * / public function handle () // få tilgang til modellen i køen for å behandle $ image = $ this-> bildet; $ full_image_path = public_path ($ image-> org_path); $ resized_image_path = public_path ('thumbs'. DIRECTORY_SEPARATOR. $ image-> org_path); // lag bildemengder fra det opprinnelige bildet $ img = \ Image :: make ($ full_image_path) -> resize (300, 200); $ Img-> Lagre ($ resized_image_path); 

Når køarbehandleren begynner å behandle en jobb, ser den etter håndtak metode. Så det er det håndtak metode som holder hovedlogikken til jobben din.

I vårt tilfelle må vi lage et miniatyrbilde av et bilde lastet opp av brukeren. Koden til håndtak Metoden er ganske enkel - vi henter et bilde fra ImageModel modell og opprett en miniatyrbilde ved hjelp av Interventions Image-biblioteket. Selvfølgelig må vi passere tilsvarende Bilde modell når vi sender vår jobb, og vi får se det på et øyeblikk.

For å teste vår nyopprettede jobb, oppretter vi et enkelt opplastingsskjema som lar brukeren laste opp et bilde. Selvfølgelig vil vi ikke skape bildeminiatyr med en gang; Vi utsetter den oppgaven slik at den kan behandles av køarbehandleren.

La oss lage en kontrollerfil på app / Http / elektro / ImageController.php som vist under.

validere ($ request, ['demo_image' => 'kreves | bilde | mimes: jpeg, png, jpg, gif, svg | max: 2048',]); $ image = $ request-> file ('demo_image'); $ input ['demo_image'] = time (). '.'. $ image-> getClientOriginalExtension (); $ destinationPath = public_path ('/ images'); $ image-> move ($ destinationPath, $ input ['demo_image']); // gjør db-oppføringen til bildet $ image = new Image; $ image-> org_path = 'images'. DIRECTORY_SEPARATOR. $ Inngang [ 'demo_image']; $ Image-> Lagre (); // utsette behandlingen av bildeminiatyrene ProcessImageThumbnails :: dispatch ($ image); returnere Omdirigering :: til ('bilde / indeks') -> med ('melding', 'Bilde lastet opp!'); 

La oss lage en tilknyttet visningsfil på ressurser / visninger / upload_form.blade.php.

       Laravel       
@if (Rute :: har ('logg inn'))
@if (Auth :: sjekk ()) Hjem @else Logg inn Registrer @endif
@slutt om

Demo Last opp skjema

@if ($ feil-> noen ())
    @foreach ($ errors-> all () som $ feil)
  • $ error
  • @endforeach
@endif @if (økt ('melding'))
økt ('melding')
@slutt om

Til slutt, la oss legge til ruter for index og laste opp handlinger i ruter / web.php fil.

Rute :: få ('bilde / indeks', 'ImageController @ index'); Rute :: post ('image / upload', 'ImageController @ upload');

I ImageController kontrolleren, den index Metoden brukes til å lage en opplastingsskjema.

offentlig funksjonsindeks (forespørsel $ forespørsel) return view ('upload_form'); 

Når brukeren sender inn et skjema, laste opp Metoden er påkalt.

offentlig funksjon opplasting (forespørsel $ forespørsel) // opplast bilde $ this-> validere ($ request, ['demo_image' => 'kreves | bilde | mimes: jpeg, png, jpg, gif, svg | max: 2048' ]); $ image = $ request-> file ('demo_image'); $ input ['demo_image'] = time (). '.'. $ image-> getClientOriginalExtension (); $ destinationPath = public_path ('/ images'); $ image-> move ($ destinationPath, $ input ['demo_image']); // gjør db-oppføringen til bildet $ image = new Image; $ image-> org_path = 'images'. DIRECTORY_SEPARATOR. $ Inngang [ 'demo_image']; $ Image-> Lagre (); // utsette behandlingen av bildeminiatyrene ProcessImageThumbnails :: dispatch ($ image); returnere Omdirigering :: til ('bilde / indeks') -> med ('melding', 'Bilde lastet opp!'); 

I begynnelsen av laste opp metode, vil du legge merke til den vanlige filopplastningskoden som flytter den opplastede filen til offentlige / bilder katalogen. Deretter legger vi inn en databasepost ved hjelp av App / Image modell.

Til slutt bruker vi ProcessImageThumbnails jobb å utsette miniatyrprosesseringsoppgaven. Det er viktig å merke seg at det er det utsendelse metode som brukes til å utsette en oppgave. På slutten blir brukeren omdirigert til opplastingssiden med en suksessmelding.

På dette tidspunktet legges jobben til arbeidsplasser bord for behandling. La oss bekrefte det ved å utstede følgende spørring.

mysql> velg * FRA lvl_jobs; | 1 | standard |  "Displayname": "App \\ Jobs \\ ProcessImageThumbnails", "jobb": "Belyse \\ Queue \\ CallQueuedHandler @ kaller", "maxTries": null, "timeout": null, "data":  "kommandonavn ":" app \\ \\ Jobs ProcessImageThumbnails " "kommando": "O: 31: \" App \\ \\ stillinger ProcessImageThumbnails \ ": 5: s: 8: \" \ u0000 * \ u0000image \"; O: 45: \ "\\ Lys Kontrakter \\ \\ Database ModelIdentifier \": 2: s: 5: \ "klasse \"; s: 9: \ "App \\ bilde \"; s: 2: \ "id \"; i: 2; s: 6: \ "\ u0000 * \ u0000job \"; N; s: 10: \ "tilkobling \"; N; s: 5: \ "kø \"; N; s: 5: \ "forsinkelse \"; N; " | 0 | NULL | 1510219099 | 1510219099 |

Du må lure på, hva tar det for å behandle en jobb da? Ikke bekymre deg - det er det vi skal diskutere i neste avsnitt.

Køarbeider

Laravel-køarbeiderens jobb er å behandle jobber som står i kø for behandling. Faktisk er det en håndverkskommando som hjelper oss med å starte køarbehandlerprosessen.

$ php artisan kø: arbeid

Så snart du kjører den kommandoen, behandler den ventende jobber. I vårt tilfelle bør det behandle ProcessImageThumbnails jobb som var i køen når brukeren lastet opp et bilde tidligere.

$ php artisan kø: arbeid [ÅÅÅÅ-MM-DD HHMMSS] Behandling: App \ Jobs \ ProcessImageThumbnails [ÅÅÅÅ-MM-DD HHMMSS] Behandlet: App \ Jobs \ ProcessImageThumbnails

Du ville ha lagt merke til at når du starter en køarbeider, fortsetter den å løpe til du dreper den manuelt eller lukker terminalen. Faktisk venter det på at neste jobb skal behandles. Så snart det er en ny jobb i køen, blir den behandlet med en gang hvis køarbehandleren kjører.

Selvfølgelig kan vi ikke holde det på den måten, så vi må finne en måte for køarbeider å løpe permanent i bakgrunnen.

Til vår redning finnes det flere prosesshåndteringsverktøy der du kan velge mellom. For å nevne noen, her er en liste:

  • Sirkus
  • DaemonTools
  • Monit
  • Supervisor
  • oppkomling

Du bør velge et verktøy som du er komfortabel med å administrere Laravel køarbeider. I utgangspunktet ønsker vi å sørge for at køarbeiderne kjører på ubestemt tid, slik at den behandler jobber i kø med en gang.

Så det er Que API til din disposisjon. Du kan bruke den i din daglige utvikling for å utsette tidkrevende oppgaver for å forbedre sluttbrukeropplevelsen.

Konklusjon

I denne artikkelen diskuterte vi kø-API i Laravel, som er veldig nyttig hvis du ønsker å utsette behandlingen av ressurskrevende oppgaver.

Vi startet med en grunnleggende introduksjon til kø-API, som innebar en diskusjon av tilkoblinger, køer og jobber. I den andre halvdelen av artikkelen opprettet vi en tilpasset køjobb som viste hvordan du kunne bruke Queue API i den virkelige verden.

For de av dere som enten bare er i gang med Laravel eller ser ut til å utvide din kunnskap, nettsted eller søknad med utvidelser, har vi en rekke ting du kan studere i Envato Market.

Du er velkommen til å bruke tilbakemeldingsskjemaet nedenfor for å legge inn dine spørsmål og forslag.