Hoe te programmeren met Yii2 Cron-services uitvoeren

Wat je gaat creëren

Als je vraagt: "Wat is Yii?" bekijk mijn eerdere tutorial: Introductie tot het Yii Framework, die de voordelen van Yii bekijkt en een overzicht bevat van wat er nieuw is in Yii 2.0, uitgebracht in oktober 2014.

In deze serie Programming With Yii2 begeleid ik lezers in gebruik van het Yii2 Framework voor PHP. In de tutorial van vandaag zal ik met u delen hoe u kunt profiteren van Yii's consolecapaciteit om cron-taken uit te voeren.

In het verleden heb ik wget gebruikt in mijn cron-taken: een webtoegankelijke URL zou mijn achtergrondtaken uitvoeren. Dit veroorzaakte beveiligingsproblemen en heeft enkele prestatieproblemen. Hoewel ik een aantal manieren heb aangehaald om risico's in de afleveringen van onze opstartseries over beveiliging te beperken, had ik gehoopt om over te schakelen naar door een console gestuurde opdrachten. En met Yii2 is het redelijk eenvoudig.

Voor het voorbeeld van vandaag zal ik console-gebaseerde cron-commando's demonstreren op mijn Twixxr-site die ik heb beschreven in deze Twitter API-aflevering. Vanwege tarieflimieten en prestatiebeheersproblemen is de Twitter API erg afhankelijk van efficiënte, betrouwbare cron-taken. Dus het is een geweldig voorbeeld om met u te delen.

Voordat ik begin, herhaal ik: ik ben altijd dankbaar voor uw ideeën en feedback. Als u een vraag of een suggestie voor een onderwerp heeft, kunt u uw mening plaatsen in de onderstaande opmerkingen. Je kunt me ook rechtstreeks op Twitter @reifman bereiken.

Wat is Cron?

Wikipedia beschrijft cron als "een op tijd gebaseerde taakplanner in Unix-achtige computerbesturingssystemen." En dat is behoorlijk accuraat. In principe voert cron alle achtergrondtaken uit die we nodig hebben om webservices uit te voeren, van logbeheer en back-ups tot API-aanvragen tot het opschonen van databases.

Als u uw bestaande cron-taken op een server wilt zien, typt u meestal sudo crontab -l en zie zoiets als dit:

# Bewerk dit bestand om taken voor cron in te voeren. # # Elke taak die moet worden uitgevoerd, moet worden gedefinieerd door een enkele # -lijn die aangeeft met verschillende velden wanneer de taak zal worden uitgevoerd # en welke opdracht moet worden uitgevoerd voor de taak # # Om de tijd te definiëren, kunt u voor # minuut (m) concrete waarden opgeven ), uur (h), dag van de maand (dom), maand (ma), # en de dag van de week (dow) of gebruik '*' in deze velden (voor 'elke'). # # Bedenk dat taken zullen worden gestart gebaseerd op het systeem # daemon's begrip van tijd en tijdzones van de cron. # # De uitvoer van de crontab-taken (inclusief fouten) wordt verzonden via # email naar de gebruiker waartoe het crontab-bestand behoort (tenzij omgeleid). # # U kunt bijvoorbeeld elke week om 05:00 uur een back-up van al uw gebruikersaccounts # uitvoeren met: # 0 5 * * 1 tar -zcf /var/backups/home.tgz / home / # # Zie voor meer informatie de man pagina's van crontab (5) en cron (8) # # mh dom mon dow commando * / 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/overnight 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

De linkerkant specificeert om deze taken elke 3 of 15 minuten of dagelijks om middernacht, enz. Te activeren, en de rechterkant is het script dat moet worden uitgevoerd. Zie ook Taken plannen met Cron-taken (Envato Tuts +).

Merk op hoe het Let's Encrypt-script een uniek console-commando is. Het loopt vanaf de opdrachtregel op onze server. Al mijn Meeting Planner-taken hierboven worden echter uitgevoerd via wget. Dat doet alsof een robot in een webbrowser was op een specifiek tijdstip waarop aanvragen werden ingediend tegen onze webtoepassing die achtergrondtaken uitvoeren.

Naast de overhead die een externe webaanvraag vereist en time-outbeperkingen op scripts op servers, moet u deze toegangspunten beveiligen. Hier is een voorbeeld van hoe Meeting Planner dit doet:

// alleen cron-taken en -beheerders kunnen de acties van deze controller uitvoeren in public-functie vóór Action (actie $) // uw aangepaste code hier, als u wilt dat de code wordt uitgevoerd vóór actiefilters // die worden geactiveerd op [[EVENT_BEFORE_ACTION]] evenement, bijv PageCache of AccessControl if (! Parent :: beforeAction ($ action)) return false;  // andere aangepaste code hier als (($ _SERVER ['REMOTE_ADDR'] == $ _SERVER ['SERVER_ADDR']) || (! \ Yii :: $ app-> user-> isGuest && \ common \ models \ User :: findOne (Yii :: $ app-> user-> getId ()) -> isAdmin ())) return true;  return false; // of false om de actie niet uit te voeren

Hiermee wordt gecontroleerd of de gebruiker is aangemeld als beheerder of lokaal op de server werkt op een identiek internet-IP-adres.

Console-gebaseerde Cron-opdrachten implementeren

Alex Makarov, een van de leidende vrijwilligers achter de ontwikkeling van het Yii Framework, was behulpzaam bij het beantwoorden van vragen voor mij omdat ik regelmatig schrijf over het kader voor Envato Tuts +. Na het lezen van mijn beveiligingspoging vroeg hij waarom ik de inherente consolemogelijkheid van Yii2 voor cron-taken niet gebruikte. Kortom, ik wist het niet.

Net zoals ik een /frontend/controllers/DaemonController.php had, maakte ik een /console/controllers/DaemonController.php. Voor deze zelfstudie doe ik dit voor de kleinere, eenvoudigere Twixxr-webservice.

Ik ben gewend om de console te gebruiken voor het uitvoeren van databasemigraties (bijv. ./ yii migrate / up 7), maar dat is alles. Ik was enthousiast om het te gebruiken voor achtergrondtaken.

Zoals ik in een eerdere tutorial schreef, vereist mijn pasgeboren site Twixxr uitgebreide achtergrondprocessen om API-oproepen regelmatig te roteren voor alle gebruikersverzoeken om vrienden te worden met invloedrijke Twitter-accounts die door vrouwen worden beheerd. 

Dit is hoe de startpagina eruit ziet:

Dus ik dacht dat Twixxr een geweldig testbed zou zijn voor het uitvoeren van een console-gebaseerde cron-controller.

De nieuwe DaemonController.php

Dit is de kern van mijn nieuwe console-gebaseerde DaemonController.php:

proces ($ TIME_START); $ time_end = microtime (true); echo 'Verwerken voor'. ($ time_end- $ time_start). ' seconden;  public function actionQuarter () // elke vijftien minuten genoemd $ x = new \ frontend \ models \ Twixxr (); $ X-> loadProfiles ();  public function actionHourly () // every hour $ current_hour = date ('G'); if ($ current_hour% 4) // elke vier uur if ($ current_hour% 6) // every six hours

Merk op dat het vrij identiek is aan de structuur van mijn front-end gebaseerde controller, maar het is veilig ontoegankelijk voor het web omdat het zich in de / consolestructuur bevindt. Er is geen Apache-webserverwebsite geconfigureerd om door dit gebied te bladeren.

Dus in het bovenstaande voorbeeld, actionFrequent () wordt om de twee à drie minuten gebeld. Het verwerkt een andere set vriendschapsverzoeken van Twixxr. Anderzijds, actionQuarter () wordt om de 15 minuten gebeld en werkt de profielinformatie bij voor het browsen van accounts. Laten we eens kijken naar hoe de planning werkt in het cron-bestand.

Het nieuwe Crontab-bestand

In wezen, in mijn crontab-bestand, vervang ik wget door een direct Linux-script zoals hierboven weergegeven voor Let's Encrypt renewals.

Jij typt sudo crontab -e om te bewerken of -l om de inhoud ervan te vermelden. Dit is mijn Twixxr cron-bestand:

$ sudo crontab -l # mh dom mon dow commando * / 3 * * * * / var / www / twixxr / yii daemon / frequent * / 15 * * * * / var / www / twixxr / yii daemon / kwartaal 0 * * * * / var / www / twixxr / yii daemon / hourly 15 1 * * * / var / www / twixxr / yii daemon / overnight 15 3 * * 5 / var / www / twixxr / yii daemon / week # 40 2 * * * / usr / sbin / automysqlbackup 30 2 * * 1 / usr / bin / letsencrypt renew >> /var/log/le-renew.log

Het is vrij eenvoudig. De linkerkant van / var / www / twixxr / yii daemon / frequent is het pad waar de yii-interpreter woont, en de rechterkant is de console-controller en de methode om te bellen.

Alles werkte vrij goed om te schakelen. Ik ben nog niet helemaal over op Meeting Planner omdat ik meer testen wil doen. Wanneer achtergrondtaken breken, is het moeilijk om te weten en moeilijk om ze te debuggen (hoewel Sentry foutregistratie veel helpt).

Problemen waarmee rekening moet worden gehouden

Een element dat ik tegenkwam, is dat de naamruimte van de console verschilt van de naamruimte aan de voorkant, dus bijvoorbeeld de component SiteHelper.php die ik in mijn zelfstudie heb ingesteld, waarin werd beschreven dat meerdere sites vanaf een enkele codebase worden uitgevoerd, is mislukt toen ik aanriep het. Het verwijderen ervan werkte, maar ik moest testen uitvoeren om er zeker van te zijn dat de onderliggende achtergrondcode nog steeds functioneerde. De omschakeling verliep echter meestal soepel.

Zoals met elke andere codeverandering, test en monitor grondig.

Wat is het volgende

Voor de toekomst zal ik onderzoek doen naar het bouwen van REST API's binnen het Yii2 Framework, dat toevallig afhankelijk is van het creëren van een afzonderlijke subboom zoals de consolestructuur, maar voor externe API's. Natuurlijk brengt dit complexe authenticatie- en beveiligingsproblemen met zich mee ... dus het zal leuk zijn om deze met u te verkennen. Ik zal API's vanuit verschillende invalshoeken bekijken. Ik ben hier eigenlijk best enthousiast over. 

Kijk uit naar komende tutorials in mijn Programming With Yii2-serie terwijl ik verder duik in verschillende aspecten van het framework. Ontdek ook de Building Your Startup With PHP-serie, waarin het proces van het bouwen van Simple Planner en Meeting Planner wordt gedocumenteerd.

Als je wilt weten wanneer de volgende Yii2-tutorial aankomt, volg me dan @reifman op Twitter of kijk op mijn instructeurspagina voor updates. 

Gerelateerde Links

  • Yii2 Developer Exchange, mijn Yii2-bronsite
  • Taken plannen met Cron-taken (Envato Tuts +)
  • Hoe cron te implementeren in Yii2 (Yii-documentatie)
  • Twixxr, de voorbeeldwebservice genoemd in