WordPress ja PHP-FPM: Konfigurointi suorituskykyynWordPressin suorituskyky ei ole vain “nopeita lisäosia” ja “hyvä välimuisti”. Se on myös palvelinprosessien fysiikkaa: kuinka monta PHP-prosessia pyörii, miten ne syntyvät, miten ne kuolevat, ja mitä tapahtuu, kun yhtä aikaa saapuu 200 pyyntöä ja kaikilla on mielipide. PHP-FPM (FastCGI Process Manager) on tässä konehuoneessa se tyyppi, joka jakaa työvuorot ja päättää, kuka pääsee kahville ja kuka jää ylitöihin.

Kun PHP-FPM on säädetty oikein, WordPress tuntuu “kevyeltä” jopa kuormassa. Kun se on säädetty huonosti, sama sivusto voi olla hidas, epävakaa ja muistisyöppö vaikka koodi olisi priimaa. Tässä artikkelissa käydään syvällisesti läpi, miten PHP-FPM konfiguroidaan nimenomaan WordPressin tarpeisiin, ja miten asetukset sidotaan oikeisiin mittareihin.

WordPressin kuormaprofiili ja miksi PHP-FPM on tärkeä

PHP-prosessit ovat rajallinen resurssi

WordPress on PHP-sovellus. Jokainen dynaaminen pyyntö tarvitsee PHP-prosessin. PHP-FPM ylläpitää prosessipoolia, josta Nginx tai Apache (FastCGI:n kautta) ottaa työntekijän käsittelemään pyynnön.

Jos prosesseja on liian vähän, pyynnöt jonoutuvat. Käyttäjälle tämä näkyy hitautena ja aikakatkaisuina. Jos prosesseja on liikaa, palvelin syö muistinsa ja alkaa swapata (eli käyttää levyä “hätämuistina”), ja sitten kaikki hidastuu – dramaattisesti.

WordPressin dynaamisuus vaihtelee

Yksi WordPress-sivusto voi olla lähes staattinen (paljon sivuvälimuistia), toinen voi olla jatkuvasti dynaaminen (WooCommerce, jäsenyydet, personoitu sisältö). PHP-FPM:n asetukset eivät ole “yleispäteviä”, vaan ne riippuvat siitä, kuinka suuri osa liikenteestä osuu PHP:lle ja kuinka raskaita pyyntöjä ne ovat.

PHP-FPM poolin perusasetukset

pm-moodi: dynamic, ondemand, static

PHP-FPM:llä on kolme pääasiallista prosessienhallintamallia.

pm = dynamic

Dynamic luo prosesseja tarpeen mukaan, mutta pitää aina minimimäärän valmiina. Tämä on yleisin ja usein paras lähtökohta WordPressille, koska se tasapainottaa vasteaikaa ja muistinkäyttöä.

pm = ondemand

Ondemand ei pidä prosesseja valmiina, vaan luo ne vasta pyynnön tullessa. Tämä voi säästää muistia, mutta lisää kylmäkäynnistyksen viivettä. Sopii ympäristöihin, joissa liikenne on piikikästä mutta keskimäärin matalaa.

pm = static

Static pitää aina täsmälleen määritellyn määrän prosesseja. Tämä voi toimia erittäin ennustettavissa kuormissa, mutta on usein turhan jäykkä WordPressille, jossa liikenne vaihtelee.

Keskeiset pool-parametrit

pm.max_children

Tämä on tärkein asetus. Se määrittää, montako PHP-prosessia poolissa voi olla yhtä aikaa. Se on suora katto samanaikaisille PHP-pyynnöille.

Arkkitehtoninen idea: pm.max_children pitäisi perustua muistilaskelmaan, ei mutuun. Kaava on käytännössä:

käytettävä muisti / yhden PHP-prosessin keskimääräinen muistinkäyttö = max_children

WordPressin prosessin muistinkäyttö riippuu lisäosista, teemasta ja PHP-versiosta. Yksi prosessi voi viedä 30 MB tai 300 MB. Tätä ei arvata, se mitataan.

pm.start_servers, pm.min_spare_servers, pm.max_spare_servers

Nämä ovat dynamic-moodin “käynnissäpitoasetukset”.

  • start_servers: montako prosessia käynnistetään alussa

  • min_spare_servers: pienin sallittu määrä “tyhjiä” prosesseja

  • max_spare_servers: suurin sallittu määrä “tyhjiä” prosesseja

WordPressissä hyvä tavoite on pitää tarpeeksi spare-prosesseja piikkien varalta, mutta ei niin paljon että muisti kuluu hukkaan. Jos spare-määrä on liian pieni, prosesseja luodaan kiireessä ja vasteajat heilahtelevat.

pm.process_idle_timeout

Ondemand-moodissa tämä määrittää, kuinka nopeasti käyttämättömät prosessit tapetaan. Liian lyhyt timeout tekee järjestelmästä “hengästyneen” piikeissä, liian pitkä syö muistia.

pm.max_requests

Tämä määrittää, montako pyyntöä yksi prosessi käsittelee ennen kuin se kierrätetään. Tämä on tärkeä, koska osa PHP-laajennuksista tai koodista voi aiheuttaa muistivuotoja pitkällä aikavälillä.

WordPressissä tyypillinen arvo on jossain sadoista muutamiin tuhansiin. Liian matala lisää prosessien uudelleenkäynnistelyä ja CPU-kuormaa, liian korkea voi pahentaa muistiongelmia.

Mittaaminen: ilman mittareita säätö on noituutta

Slow log ja request_terminate_timeout

request_slowlog_timeout ja slowlog

Näillä saat listan hitaista PHP-pyynnöistä ja niiden stack trace -jäljen. WordPressissä tämä on kultaa, koska se paljastaa hitaat lisäosat, teeman funktiot tai ulkoiset API-kutsut.

request_terminate_timeout

Tämä tappaa pyynnön, joka kestää liian kauan. Tuotannossa tämä estää yksittäisiä “jumittavia” pyyntöjä syömästä kaikkia prosesseja.

Status-sivu ja pm.status_path

PHP-FPM voi tarjota status-endpointin, josta näkee mm. aktiiviset prosessit, jonotuksen ja saavutetun maksimikuorman. Kun tätä seuraa kuormapiikeissä, näkee nopeasti, onko pullonkaula prosessimäärässä vai jossain muualla.

Tärkeät oireet ja mitä ne tarkoittavat

  • 502/504-virheet kuormassa: prosessit loppuvat tai upstream timeoutit ovat liian tiukat

  • korkea load + swap: max_children liian korkea tai prosessit liian isoja

  • korkea CPU ilman vastaavaa liikennettä: jokin pyyntö on raskas, välimuistit puuttuvat tai opcode cache puuttuu

WordPress-spesifit optimoinnit PHP-FPM:n rinnalla

OPcache on käytännössä pakollinen

OPcache tallentaa PHP:n käännetyt opcode-tulokset muistiin, jolloin samaa koodia ei tarvitse “kääntää” jokaisella pyynnöllä. WordPressissä tämä parantaa sekä vasteaikaa että vähentää CPU-kuormaa.

OPcache-asetuksissa keskeistä on, että muistia on riittävästi ja että revalidate on järkevästi asetettu kehitys- vs tuotantoympäristöissä.

Realpath cache ja tiedostojärjestelmä

WordPress tekee paljon tiedostopolkujen tarkistusta. PHP:n realpath cache vähentää tiedostojärjestelmäkyselyitä ja voi auttaa etenkin, jos levy on hidas tai käytössä on verkkolevy.

Välimuistit: sivuvälimuisti ja object cache

PHP-FPM:ää ei kannata “pelastaa” pelkällä prosessimäärällä, jos suurin osa liikenteestä voidaan palvella ilman PHP:tä. Nginx fastcgi_cache tai erillinen page cache -kerros vähentää PHP:lle osuvien pyyntöjen määrää radikaalisti.

Object cache (Redis/Memcached) vähentää tietokantakuormaa ja lyhentää PHP-pyyntöjen kestoa. Lyhyemmät pyynnöt tarkoittavat, että sama prosessimäärä pystyy palvelemaan enemmän liikennettä.

Käytännön lähestymistapa konfigurointiin

1) Selvitä PHP-prosessin keskimääräinen muistinkäyttö

Tee kuormaa vastaava testiliikenne (tai mittaa tuotannossa turvallisesti) ja katso prosessien RSS-muistit. WordPressissä kannattaa mitata erikseen:

  • anonyymit sivulataukset välimuistin läpi vs ilman

  • kirjautuneet käyttäjät

  • WooCommerce-kassa ja my account -sivut

  • WP-Admin (editori, mediakirjasto)

2) Päätä muistibudjetti PHP-FPM:lle

Älä anna PHP-FPM:n käyttää kaikkea muistia. Jätä tilaa:

  • tietokannalle (jos samalla palvelimella)

  • Redis/Memcachedille

  • web-palvelimelle

  • kernelille ja file cachelle

3) Aseta max_children ja säädä spare-arvot

Kun max_children on laskettu, säädä start/min/max spare niin, että piikit eivät aiheuta jatkuvaa prosessien luontia, mutta muistia ei seiso tyhjänpanttina.

4) Lisää turvakaiteet

  • pm.max_requests estämään pitkäaikaiset muistiongelmat

  • request_terminate_timeout estämään jumit

  • slowlog paljastamaan pullonkaulat

5) Tarkkaile ja iterioi

Säätö tehdään mittareilla: jonotus, vasteajat, muistinkäyttö, CPU, error-logit. Hyvä konfiguraatio näyttää tylsältä grafiikoissa. Kun mittarit ovat “rauhallisia”, käyttäjät ovat onnellisia.

Tyypilliset virheet, jotka hidastavat WordPressiä

Max_children liian suuri

Tämä on klassinen “lisätään prosesseja, niin nopeutuu” -harha. Jos jokainen prosessi vie paljon muistia, iso max_children johtaa swappiin ja romahdukseen.

Liian tiukat upstream timeoutit

Nginxin fastcgi_read_timeout tai Apachen ProxyTimeout voi olla liian matala. Silloin raskaat mutta normaalit toiminnot (esim. kuvien generointi, varmuuskopio, WooCommerce) katkeavat.

Slowlog puuttuu

Ilman slowlogia optimointi kohdistuu väärin. Usein ongelma ei ole PHP-FPM:n prosessimäärä vaan yksi lisäosa, joka tekee ulkoisia HTTP-kutsuja jokaisella pyynnöllä.

Lopuksi: PHP-FPM on kapasiteettisuunnittelua

PHP-FPM:n konfigurointi WordPressille on pohjimmiltaan kapasiteetin hallintaa: paljonko samanaikaisia pyyntöjä voidaan palvella ilman että muisti loppuu ja ilman että jonotus kasvaa. Kun tähän lisätään WordPressin omat välimuistit ja hyvä kyselyhygienia, tulos on järjestelmä, joka ei vain toimi nopeasti, vaan pysyy nopeana myös silloin kun internet päättää rynnätä ovesta sisään samaan aikaan.