Skip to main content

29 Tekniikkaa

29Tekniikka logo
WordPressin ajastettu toiminto voi näyttää hallinnassa täysin normaalilta.
Tehtävä on olemassa. Seuraava suoritusaika näkyy. Lisäosassa ei ole mitään selvää virheilmoitusta.
Silti tehtävä ei koskaan näytä tapahtuvan.
Ajastettu julkaisu jää odottamaan. Sähköpostia ei lähde. Verkkokaupan taustatehtävä ei valmistu. Jonkin lisäosan pitäisi päivittää tietoja yön aikana, mutta aamulla huomataan, ettei mitään ole tapahtunut.
Tässä kohtaa puhutaan yleensä WordPress Cronista eli WP-Cronista.
Ongelma on kuitenkin usein siinä, että WP-Cronia ajatellaan tavallisen palvelimen cron-ajon tapaan. WordPressin oma ajastus toimii hieman eri tavalla.

WP-Cron ei ole jatkuvasti käynnissä

Tämä on ensimmäinen asia, joka kannattaa ymmärtää.

WP-Cron ei normaalisti ole palvelimella jatkuvasti käynnissä oleva prosessi. WordPress tarkistaa sivulatausten yhteydessä, onko ajastettuja tehtäviä myöhässä.

Jos tehtävä on määrä suorittaa, WordPress yrittää käynnistää cron-ajon.

Jos sivustolla ei käy ketään, ajastus ei siis käyttäydy samalla tavalla kuin järjestelmän oma cron.

Pienellä yrityssivustolla tämä voi olla aivan riittävä ratkaisu.

Jos sivusto on hiljainen öisin ja tehtävä pitäisi suorittaa esimerkiksi tasan kahdelta, kellonaika ei kuitenkaan ole yhtä varma kuin palvelimen oikealla cron-ajolla.

Tämä ero selittää yllättävän monta “Cron ei toimi” -tilannetta.

Tehtävää ei ehkä ole edes ajastettu

Joskus ongelma on paljon yksinkertaisempi.

Lisäosa yrittää rekisteröidä tapahtuman, mutta sitä ei koskaan synny.

Mukautetussa WordPress-koodissa ajastus tehdään yleensä wp_schedule_event()- tai wp_schedule_single_event()-funktion avulla. Varsinaisen työn suorittava funktio liitetään action-hookiin. Jos hookia ei ole rekisteröity oikein, tapahtuma voi olla listalla mutta mitään hyödyllistä ei tapahdu.

Tämä on hyvä erottaa kahdeksi eri ongelmaksi:
Tapahtumaa ei ole olemassa.
Tai:
Tapahtuma on olemassa, mutta sen suorittaminen epäonnistuu.
Näitä ei kannata tutkia samalla tavalla.
Tarkista ensin, näkyykö tapahtuma

Jos palvelimella on WP-CLI käytössä, cron-tapahtumia voi tarkastella suoraan:
wp cron event list

Komento näyttää esimerkiksi hookin, seuraavan suoritusajan ja toistuvuuden.

Tämä on usein paljon parempi lähtökohta kuin WordPressin hallinnan kautta arvaaminen.

Jos odotettu tapahtuma puuttuu kokonaan, ongelma on todennäköisesti ajastuksen luomisessa.

Jos tapahtuma löytyy ja sen seuraava ajoaika on jo mennyt, silloin katse siirtyy cronin käynnistymiseen tai itse tehtävään.

Sivuston liikenne voi vaikuttaa asiaan

Ajatellaan pientä yrityksen verkkosivustoa.
Sivustolla käy päivällä paljon ihmisiä. Yöllä liikennettä on lähes olemattomasti.
Jos WordPressissä on tehtävä, jonka pitäisi ajaa esimerkiksi kello 03.00, sitä ei välttämättä suoriteta juuri silloin. WP-Cron tarvitsee normaalisti uuden tilaisuuden käynnistyä, ja käytännössä seuraava sivulataus voi olla se hetki, jolloin myöhässä oleva tapahtuma huomataan.
Tämä ei tarkoita, että WP-Cron olisi rikki.
Se tarkoittaa, että kyseessä ei ole tarkalleen sama mekanismi kuin käyttöjärjestelmän cron.
Jos tehtävän ajoituksella on liiketoiminnallisesti merkitystä, kannattaa harkita palvelimen tai hosting-ympäristön varsinaista cron-ajastinta.

Loopback-yhteys voi estää koko ajon

WordPress käyttää loopback-pyyntöjä käynnistääkseen ajastettuja tapahtumia.
Käytännössä palvelin yrittää ottaa yhteyden omaan WordPress-sivustoonsa. Jos tämä yhteys epäonnistuu, WP-Cronin käynnistyminen voi epäonnistua. WordPress tarkistaa loopback-yhteyksiä myös Site Health -toiminnoissa.
Tämä on erityisen kiinnostava ongelma silloin, kun:
  • sivusto toimii muuten normaalisti
  • hallinta toimii
  • käyttäjät näkevät sivut normaalisti
  • mutta ajastetut tapahtumat eivät käynnisty
Palvelimen palomuuri, väärä DNS-asetus, SSL-ongelma tai palvelimen verkkoympäristö voi estää yhteyden sivustolta takaisin itseensä.
Silloin cronin tutkiminen pelkän WordPress-hallinnan kautta ei välttämättä paljasta todellista syytä.

Site Health kannattaa katsoa

➢ WordPressin Site Health -näkymässä oleva loopback-testi on tässä hyödyllinen.
➢ Jos WordPress kertoo, ettei sivusto pysty suorittamaan loopback-pyyntöä, sitä ei kannata ohittaa vain siksi, että etusivu toimii.
➢ Loopbackeja käytetään WP-Cronin lisäksi myös muihin WordPressin toimintoihin.
➢ Jos testi epäonnistuu, seuraava kysymys onkin:
  • Se voi johtaa palvelimen, DNS:n, SSL:n, palomuurin tai lisäosan tutkimiseen.
Miksi palvelin ei pysty muodostamaan yhteyttä omaan WordPressiin?

Lisäosa voi rikkoa cron-ajon

Kaikki Cron-ongelmat eivät johdu itse ajastuksesta.

Ajastettu tehtävä voi käynnistyä aivan normaalisti ja kaatua vasta sen jälkeen.

Esimerkiksi lisäosa voi yrittää hakea tietoja ulkoisesta API:sta. Yhteys ei onnistu. PHP-prosessi saa virheen. Tai tietokantakysely kestää niin kauan, ettei tehtävä pääse loppuun.

WordPressin näkökulmasta cron käynnistyi.

Käyttäjän näkökulmasta tehtävä ei silti koskaan valmistunut.

Tässä vaiheessa kannattaa tutkia itse hookin toimintaa eikä enää vain sitä, käynnistyykö WP-Cron.

Cron-tehtävä voi olla olemassa kahteen kertaan

Mukautetussa WordPress-kehityksessä on myös toinen helposti syntyvä ongelma.

Sama tapahtuma ajastetaan useammin kuin kerran.

Tätä voi tapahtua esimerkiksi silloin, jos wp_schedule_event() kutsutaan ilman tarkistusta aina, kun lisäosa latautuu.

Seurauksena sama työ voi päätyä cron-järjestelmään useita kertoja.

WordPressin dokumentaatio suosittelee käyttämään wp_next_scheduled()-tarkistusta, jotta samaa toistuvaa tapahtumaa ei rekisteröidä vahingossa uudelleen. Duplikaatit voivat myös kasvattaa cron-tietoja ja aiheuttaa turhaa tietokantakuormaa.

Pahimmillaan yksi taustatehtävä alkaa tehdä samaa työtä monta kertaa.

DISABLE_WP_CRON voi olla syy

Joissakin tuotantoympäristöissä WordPressin oma cron-käynnistys poistetaan käytöstä:
define( ‘DISABLE_WP_CRON’, true );
Tämä ei itsessään ole virhe.
Tällöin on kuitenkin oltava jokin toinen tapa käynnistää wp-cron.php, esimerkiksi palvelimen varsinainen cron-ajastus.
Jos WordPressin oma cron on poistettu käytöstä eikä korvaavaa ajastusta ole määritetty, lopputulos on melko suoraviivainen:
ajastetut tehtävät eivät käynnisty.
WP-CLI:n wp cron test osaa myös tarkistaa, onko WP-Cronin käynnistys käytettävissä ja onnistuuko sen HTTP-pohjainen käynnistys.

Cron voi käynnistyä, mutta tehtävä epäonnistuu

Tämä ero kannattaa pitää mielessä koko tutkimuksen ajan.

Jos ajat WP-CLI:llä:
wp cron event run --due-now

WordPress yrittää suorittaa kaikki tällä hetkellä erääntyneet tapahtumat.

Jos tehtävä toimii näin mutta ei normaalin liikenteen yhteydessä, ongelmaa kannattaa etsiä cronin käynnistysmekanismista.

Jos tehtävä epäonnistuu myös WP-CLI:n kautta, vika on todennäköisemmin itse callbackissa tai sen käyttämässä ympäristössä.

Tämä on yksi nopeimmista tavoista rajata ongelmaa.

Aikakatkaisu voi tehdä cronista epäluotettavan

Kaikki cron-tehtävät eivät ole samanlaisia.

Yksi tehtävä päivittää muutaman tietueen. Toinen käy läpi tuhansia tuotteita ja tekee samalla ulkoisia API-kutsuja.

Jälkimmäinen voi olla liian raskas suoritettavaksi yhtenä pakettina.

Jos prosessi kestää pitkään, PHP:n aikaraja, palvelimen resurssit tai ulkoisen palvelun hitaus voi tulla vastaan.

Silloin cronin muuttaminen “toimimaan nopeammin” ei välttämättä ole oikea ratkaisu.

Tehtävä kannattaa ehkä jakaa pienempiin eriin.

Esimerkiksi tuhansien tuotteiden käsittely voidaan tehdä sadoittain sen sijaan, että koko työ yritetään tehdä yhdellä pyynnöllä.

Cron-tehtävän pitäisi olla mahdollisimman tylsä

Tämä kuulostaa ehkä oudolta, mutta tuotannossa se on hyvä tavoite.
Ajastetun tehtävän ei pitäisi tehdä valtavaa määrää asioita yhden suorituksen aikana.
Jos tehtävä epäonnistuu puolivälissä, pitää myös tietää, mitä ehti tapahtua.
Jos sama tehtävä käynnistyy uudelleen, syntyykö duplikaatteja?
Lähetetäänkö sama sähköposti uudelleen?
Päivitetäänkö sama tietue kahdesti?
Mitä tapahtuu, jos ulkoinen API vastaa viisi minuuttia myöhässä?
Nämä kysymykset ovat paljon olennaisempia kuin se, näkyykö cron WordPressin hallinnassa vihreänä.

Tuotannossa oikea cron voi olla parempi vaihtoehto

Jos sivustolla on paljon liikennettä ja tehtävien ajoitus ei ole kriittinen, WP-Cron voi olla aivan riittävä.
Jos kyseessä on kuitenkin esimerkiksi:
  • säännöllinen datan synkronointi
  • suurehko tuotekatalogi
  • raporttien muodostaminen
  • integraatioiden käsittely
  • tietojen siirtäminen järjestelmästä toiseen
palvelimen oma cron tai muu hallittu ajastus voi olla järkevämpi.
WordPress voidaan määrittää käyttämään ulkoista ajastinta sen sijaan, että jokainen sivulataus yrittää osallistua cronin käynnistämiseen.
Tärkeää on vain tietää, kumpaa mallia tuotannossa käytetään.
Sekamuotoinen ympäristö, jossa WP-Cron on osittain poistettu käytöstä ja kukaan ei tiedä, mikä oikeasti käynnistää tehtävät, on paljon vaikeampi ylläpitää.

Näin lähtisin tutkimaan rikkinäistä Cronia

Jos tuotannossa huomataan, että WordPressin ajastetut tehtävät ovat jääneet suorittamatta, etenisin ensin melko pienillä testeillä.
Katsoisin, näkyykö kyseinen tapahtuma cron-listassa.
Sen jälkeen tarkistaisin, onko tapahtuma myöhässä vai puuttuuko se kokonaan.
Seuraavaksi testaisin WP-Cronin käynnistymisen:
wp cron test
Jos WP-CLI on käytettävissä, ajaisin tarvittaessa kyseisen tapahtuman myös käsin.
Tämän jälkeen olisi jo paljon helpompi sanoa, onko ongelma:
  • tapahtuman rekisteröinnissä
  • cronin käynnistymisessä
  • loopback-yhteydessä
  • itse callback-funktiossa
  • palvelimen resursseissa
  • ulkoisessa palvelussa
  • vai siinä, että tehtävä on yksinkertaisesti liian suuri yhdelle ajolle.
Tässä järjestyksessä tutkiminen säästää yleensä aikaa.

Lopuksi

WordPress Cron ei ole varsinaisesti vaikea järjestelmä. Ongelmat alkavat usein siinä vaiheessa, kun sen toiminta oletetaan samanlaiseksi kuin palvelimen tavallisen cron-ajastimen.
WP-Cron tarvitsee normaalisti tilaisuuden käynnistyä. Loopback-yhteyden pitää toimia. Ajastetun tapahtuman pitää olla olemassa ja sen callbackin pitää pystyä suorittamaan työnsä.
Jos jokin näistä kohdista pettää, käyttäjälle näkyy lopulta sama asia: mitään ei tapahtunut.
Siksi en lähtisi ensimmäisenä asentamaan uutta cron-lisäosaa tai poistamaan WordPressistä puolta lisäosista.
Ensin selvittäisin, onko tapahtuma olemassa, yrittääkö WordPress suorittaa sen ja missä kohtaa suoritus pysähtyy.
Kun tuo kohta löytyy, varsinainen korjaus on yleensä paljon pienempi kuin aluksi näyttää.