Hur man programmerar med Yii2 Running Cron Services

Vad du ska skapa

Om du frågar, "Vad är Yii?" kolla in min tidigare handledning: Introduktion till Yii Framework, som granskar fördelarna med Yii och innehåller en översikt över vad som är nytt i Yii 2.0, släppt i oktober 2014.

I denna programmering med Yii2-serien guidar jag läsare som använder Yii2 Framework for PHP. I dagens handledning delar jag med dig hur du utnyttjar Yiis konsolkapacitet för att köra cron-jobb.

I det förflutna har jag använt wget i mina cronjobb - en webbåtkomlig URL skulle köra mina bakgrundsuppgifter. Detta väckte säkerhetsproblem och har vissa prestanda problem. Medan jag tog upp några sätt att mildra riskerna i vår uppstartsserie episoder om säkerhet, hade jag hoppats att övergå till konsolstyrda kommandon. Och med Yii2 är det ganska enkelt.

För dagens exempel visar jag konsolbaserade cron-kommandon på min Twixxr-webbplats som jag beskrivit i denna Twitter API-episod. På grund av gränsgränser och prestationshanteringsfrågor är Twitter API mycket beroende av effektiva och pålitliga cron-uppgifter. Så det är ett bra exempel att dela med dig.

Innan jag börjar kommer jag att upprepa: Jag är alltid uppskattad av dina idéer och feedback. Om du har en fråga eller ett ämnesförslag, vänligen lägg in dina tankar i kommentarerna nedan. Du kan också nå mig på Twitter @ reifman direkt.

Vad är Cron?

Wikipedia beskriver cron som "en tidsbaserad jobbschemaläggare i Unix-liknande datoperativsystem." Och det är ganska noggrant. I grund och botten driver cron alla bakgrundsuppgifter som vi behöver för att köra webbtjänster, från loghantering och säkerhetskopiering till API-förfrågningar till databashantering.

För att se dina befintliga cronjobb på en server skriver du vanligtvis sudo crontab-l och se något så här:

# Redigera den här filen för att införa uppgifter som ska köras av cron. # # Varje uppgift att köra måste definieras genom en enda rad # som indikerar med olika fält när uppgiften kommer att köras # och vilket kommando som ska köras för uppgiften # # För att definiera tiden du kan ge konkreta värden för # minut (m ), timme (h), dag månad (dom), månad (mån), # och veckodag (dow) eller använd '*' i dessa fält (för 'någon'). # # Observera att uppgifterna kommer att startas baserad på crons system # demonens uppfattning om tid och tidszoner. # # Resultatet av crontabjobben (inklusive fel) skickas via # email till användaren som crontabfilen tillhör (om inte omdirigerad). # # Till exempel kan du köra en säkerhetskopia av alla dina användarkonton # vid 5 am varje vecka med: # 0 5 * * 1 tar -zcf /var/backups/home.tgz / home / # # För mer information se manuella sidor av crontab (5) och cron (8) # # mh dom mon dow kommando * / 3 * * * * wget -O / dev / null http://meetingplanner.io/daemon/frequent * / 15 * * * * wget -O / dev / null http://meetingplanner.io/daemon/quarter 0 * * * * wget -O / dev / null http://meetingplanner.io/daemon/hourly 15 1 * * * wget -O / dev / null http://meetingplanner.io/daemon/oververnight 40 2 * * * / usr / sbin / automysqlbackup 15 3 * * 5 wget -O / dev / null http://meetingplanner.io/daemon/weekly 30 2 * * 1 / opt / letsencrypt / letsencrypt-auto renew >> >> /var/log/le-renew.log

Vänster sida anger att du ska aktivera dessa uppgifter var 3: e eller 15 minuter eller dagligen vid midnatt, etc., och på höger sida är manuset att springa. Se även Schemaläggningsuppgifter med Cron Jobs (Envato Tuts +).

Lägg märke till hur Let's Encrypt-skriptet är ett unikt konsolkommando. Det går från kommandoraden på vår server. Däremot kör alla mina mötesplaneringsuppgifter ovan via wget. Det verkar som om en robot var i en webbläsare vid en viss tid som körde förfrågningar mot vår webbapplikation som utför bakgrundsuppgifter.

Förutom den överliggande kostnad som en extern webbförfrågan kräver och tidsbegränsningar på skript på servrar måste du säkra dessa åtkomstpunkter. Här är ett exempel på hur mötesplaneraren gör det:

// Endast cron-jobb och administratörer kan köra den här kontrollenhems handlingar allmänna funktionen föreAction ($ action) // din anpassade kod här, om du vill att koden ska köras före åtgärdsfilter, // som utlöses på [[EVENT_BEFORE_ACTION]] händelse, t.ex. PageCache eller AccessControl om (! Förälder :: beforeAction ($ action)) return false;  // annan anpassad kod här om (($ _SERVER ['REMOTE_ADDR'] == $ _SERVER ['SERVER_ADDR']) || (! \ Yii :: $ app-> user-> isGuest && \ common \ models \ User :: findOne (Yii :: $ app-> user-> getId ()) -> isAdmin ())) return true;  returnera false; // eller felaktigt att inte köra åtgärden

Det verifierar att användaren antingen är inloggad som administratör eller körs lokalt på servern på en identisk Internet-IP-adress.

Implementera konsolbaserade Cron-kommandon

Alex Makarov, en av de ledande volontärerna bakom Yii Framework, har hjälpt mig att svara på frågor som jag regelbundet skriver om ramen för Envato Tuts +. Efter att ha läst min säkerhetsavdelning frågade han varför jag inte använde Yii2s inneboende konsolfunktion för cron-jobb. I grund och botten visste jag inte om det.

Precis som jag hade en /frontend/controllers/DaemonController.php, skapade jag en /console/controllers/DaemonController.php. För denna handledning gör jag det för den enklare och enklare Twixxr webbtjänsten.

Jag är van att använda konsolen för att köra databasmigrationer (t.ex.. ./ yii migrera / upp 7), men det är allt. Jag var ivriga att försöka använda den för bakgrundsuppgifter.

Som jag skrev om i en tidigare handledning, kräver min nyfödda webbplats Twixxr omfattande bakgrundsprocesser för att regelbundet rotera API-samtal för alla användarförfrågningar om att vara vän med inflytelserika Twitter-konton som innehas av kvinnor. 

Så här ser hemsidan ut:

Så jag trodde Twixxr skulle göra en bra testbädd för att köra en konsolbaserad cron-controller.

Den nya DaemonController.php

Här är kärnan i min nya konsolbaserade DaemonController.php:

förfarande ($ TIME_START); $ time_end = mikrotime (true); echo "Behandling för". ($ time_end- $ time_start). ' sekunder;  public function actionQuarter () // heter varje femton minuter $ x = new \ frontend \ models \ Twixxr (); $ X-> loadProfiles ();  offentlig funktion actionHourly () // varje timme $ current_hour = date ('G'); om ($ current_hour% 4) // var fjärde timme om ($ current_hour% 6) // var sjätte timme

Observera att det är ganska identiskt med strukturen på min front-end-baserade kontroller, men det är säkert otillgängligt för webben eftersom det finns i / konsolträdet. Ingen Apache webbserver webbplats är konfigurerad att bläddra i det här området.

Så, i exemplet ovan, actionFrequent () kommer att ringas varannan tre till tre minuter. Det behandlar en annan uppsättning Twixxr vänskapsförfrågningar. Å andra sidan, actionQuarter () anropas var 15: e minut och uppdaterar profilinformationen för bläddringskonton. Låt oss titta på hur schemaläggningen fungerar i cron-filen.

Den nya Crontab-filen

I huvudsak, i min crontab-fil, ersätter jag wget med ett direkt Linux-skript som visas ovan för Låt oss kryptera förnyelser.

Du skriver sudo crontab -e att redigera eller -l att lista dess innehåll. Här är min Twixxr cron-fil:

$ sudo crontab -l # mh dom mon dow kommando * / 3 * * * * / var / www / twixxr / yii demon / frekvent * / 15 * * * * / var / www / twixxr / yii daemon / quarter 0 * * * * / var / www / twixxr / yii daemon / timme 15 1 * * * / var / www / twixxr / yii daemon / övernattning 15 3 * * 5 / var / www / twixxr / yii demon / vecka # 40 2 * * * / usr / sbin / automysqlbackup 30 2 * * 1 / usr / bin / letsencrypt förnya >> /var/log/le-renew.log

Det är ganska enkelt. Vänster sida av / var / www / twixxr / yii demon / frekvent är den väg där yi-tolken lever, och den högra sidan är konsolkontrollen och metoden att ringa.

Allt fungerade ganska bra omkoppling. Jag har inte bytt mötesplanerare över än, precis som jag vill göra mer testning. När bakgrundsuppgifterna bryter är det svårt att veta och svårt att felsöka dem (även om Sentry Error Logging hjälper till mycket).

Frågor att överväga

Ett element som jag stötte på är att konsolens namnrymd skiljer sig från namnet på den främre delen, så till exempel den SiteHelper.php-komponent jag satt upp i min handledning, som beskrivde att köra flera webbplatser från en enda kodbas, misslyckades när jag påkallade Det. Att ta bort det fungerade, men jag behövde springa test för att se till att den bakomliggande bakgrundskoden fortfarande fungerade. Dock gick övergången smidigt.

Som med någon annan kodändring, test och övervaka noggrant.

Vad kommer härnäst

I framtiden kommer jag att utforska att bygga REST APIs inom Yii2 Framework, som för förlusten av att skapa ett distinkt sub-träd som konsolträdet men för externa API-er. Det här medför naturligtvis komplexa autentiserings- och säkerhetsproblem ... så det blir roligt att utforska dessa med dig. Jag ska titta på API: er från flera vinklar. Jag är faktiskt ganska upphetsad över det här. 

Titta på kommande handledningar i min programmering med Yii2-serien när jag fortsätter att dyka in i olika aspekter av ramen. Vänligen utforska också Bygga din start med PHP-serien, som dokumenterar processen med att bygga Simple Planner och Meeting Planner.

Om du vill veta när nästa Yii2 handledning kommer, följ mig @reifman på Twitter eller kolla min instruktörssida för uppdateringar. 

relaterade länkar

  • Yii2 Developer Exchange, min Yii2 resurs webbplats
  • Schemaläggningsuppgifter med Cron Jobs (Envato Tuts +)
  • Så här implementerar du cron i Yii2 (Yii Dokumentation)
  • Twixxr, den webbservicetjänst som nämns inom