...

WordPress PHP-FPM Børn: Forkerte værdier blokerer sider

PHP-FPM Børn afgør i WordPress, om forespørgsler kører glat eller bliver hængende i køen. Jeg vil vise dig, hvordan forkert pm.max_børn-værdier blokerer sider, optager RAM, og hvordan jeg beregner rene værdier.

Centrale punkter

Før jeg går i dybden, vil jeg kort opsummere de vigtigste budskaber:

  • pm.max_børn bestemmer, hvor mange samtidige PHP-anmodninger, der kører.
  • For lidt Børn genererer køer, 502/504 og høj TTFB.
  • For meget fører til RAM-flaskehalse, swap og OOM-dødsfald.
  • Formeltilgængelig PHP RAM / processtørrelse × 0,7-0,8.
  • Iterativ Tuning med overvågning giver den bedste ydelse på lang sigt.

Hvorfor blokerer forkerte PHP-FPM-børnesider

Hver dynamisk WordPress-anmodning kræver sin egen Arbejder, og det er netop disse processer, som poolen kontrollerer via pm.max_children. Hvis jeg sætter værdien for lavt, hober forespørgslerne sig op i en kø, og TTFB stiger mærkbart. Hvis jeg sætter værdien for højt, bruger hver underordnet proces ekstra RAM, og serveren skifter til swap. Alt går langsommere i swap, indtil Apache eller Nginx rapporterer 502/504, eller OOM-killeren afslutter processerne. Sundt throughput opnås kun, når antallet af børn matcher det reelle RAM-budget og projektets belastning.

Formlen for pm.max_children i praksis

Jeg starter med den enkle formel: tilgængelig RAM til PHP divideret med den gennemsnitlige størrelse af en underordnet proces, ganget med en Sikkerhedsfaktor Jeg bestemmer RAM pr. proces med ps og RSS-kolonnen; for typiske WordPress-stakke er 50-250 MB ofte korrekt. På en 4 GB-server reserverer jeg hukommelse til Linux-, database- og cachetjenester og efterlader omkring 1,5-2 GB til PHP forblive. Hvis procesgennemsnittet f.eks. er 100 MB, er 2.000 / 100 × 0,75 = 15 børn. Dette tal fungerer som et udgangspunkt, som jeg forfiner i henhold til belastningsprofil, caching og plugin-mix.

Startværdier for typiske WordPress-opsætninger

For små blogs med 2 GB RAM, 8 børn, pm = dynamic og en pm.max_requests på ca. 800. Til mellemstore projekter med 4 GB RAM indstiller jeg 12 children, start_servers 4, min_spare_servers 4. Store shops med 8 GB RAM eller mere har gavn af 21-40 children; hvis belastningen er permanent høj, kan pm = static sikre konstant gennemstrømning. Derefter tjekker jeg forholdet mellem CPU-udnyttelse, RAM-udnyttelse og svartider for at foretage finjusteringer. Hvis du vil dykke dybere ned, kan du finde baggrundsinformation på optimale PHP-FPM-indstillinger.

Måling af processer: Sådan bestemmes RAM-krav

Jeg bestemmer først processernes live-størrelse, før jeg sætter værdier, for krystalkugler hjælper ikke her og koster penge. Strøm. Kommandoen ps -ylC php-fpm -sort:rss returnerer RSS-størrelserne, som jeg overvåger i løbet af et par minutter. Processer vokser ofte under opdateringer eller cron-jobs, og derfor inkluderer jeg spidsbelastninger i beregningen. Jeg bruger også htop og free -h til at tjekke RAM-reserverne og mængden af swap. Jeg bruger disse data til at bestemme et pålideligt gennemsnit og vælge en konservativ sikkerhedsfaktor.

Et overblik over vigtige parametre

Ud over pm.max_children bestemmer andre puljeindstillinger, hvor rent WordPress behandler anmodninger, og hvor godt det frigør hukommelse, hvilket mærkbart reducerer Stabilitet pm regulerer tilstanden: dynamic tilpasser antallet af processer til belastningen, static opretholder et fast antal. pm.max_requests forhindrer opblødning af hukommelsen ved at genstarte processer efter X anmodninger. request_terminate_timeout beskytter mod ophængning forårsaget af defekte eller langsomme scripts. Med dette sæt dækker jeg 90 procent af de virkelige praktiske tilfælde.

Parametre Funktion WordPress-anbefaling
pm Processtyringstilstand dynamisk til variabel belastning; statisk til permanent høj trafik
pm.max_børn Maksimalt antal samtidige arbejdere Tilgængelig PHP RAM / processtørrelse × 0,75
pm.max_anmodninger Genbrug af processer 300-1.000; snarere lavere med WooCommerce
request_terminate_timeout Annullering af langvarige anmodninger 60-120 sekunder mod bøjler

Dynamisk, ondemand eller statisk - hvilken tilstand er den rigtige for dig?

Jeg vælger den tilstand, der passer til belastningsprofilen: dynamisk er min standard, fordi den fleksibelt tilpasser antallet af aktive processer og dermed sparer RAM, når der ikke sker så meget. statisk Jeg bruger det, når belastningen er konstant, og jeg har brug for hårde forpligtelser med hensyn til ventetid og gennemstrømning - for eksempel under kampagner eller salg. ondemand er velegnet til servere med lange inaktivitetsfaser: Processer oprettes kun, når det er nødvendigt, og afsluttes igen efter inaktivitet. Afvejningen er koldstart; den første anmodning pr. ny proces føles langsommere. For ondemand sætter jeg pm.process_idle_timeout rent (f.eks. 10-20s), med dynamisk holder jeg start_servere, min_spare_servere og max_spare_servere tæt, så bassinet hurtigt bliver stort, men ikke „puster sig op“.

Eksempel på konfiguration af din pool

På Debian/Ubuntu er pool-filen normalt placeret under /etc/php/8.x/fpm/pool.d/www.conf, hvilket giver mig en klar Struktur til tilpasninger. Jeg sætter pm til dynamisk, forankrer en realistisk værdi for pm.max_children og holder reserveserveren tæt. Jeg sætter genbrug til 500 for at begrænse lækager og RAM-forøgelser tidligt i forløbet. Efter hver ændring tester jeg belastningen og fjerner flaskehalse, før jeg øger værdierne yderligere. For baggrundsinformation om grænseværdier, se indsigten på Optimer pm.max_children.

pm = dynamisk
pm.max_children = 15
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 8
pm.max_requests = 500
request_terminate_timeout = 90s

Flere bassiner, stikkontakter og ren isolering

For flere projekter eller klart adskilte roller (frontend vs. admin/REST) opsætter jeg separate puljer med sin egen bruger og socket. På den måde begrænser hver pool sine egne børn, og en afvigelse blokerer ikke for resten. På en host foretrækker jeg Unix-sokler sammenlignet med TCP (listen = /run/php/site.sock) - lavere latenstid, mindre overhead. Jeg bruger TCP mellem Nginx/Apache og PHP-FPM på forskellige hosts/containere. Jeg bruger listen.ejer, listen.gruppe og listen.mode konsekvent og om nødvendigt hæve listen.backlog så korte spidsbelastninger ikke resulterer i forbindelsesfejl. Med en dedikeret admin-pool kan jeg opnå en strammere request_terminate_timeout drev og pm.max_anmodninger lavere uden at bremse den caching-stærke frontend-pool.

Genkende symptomer og reagere korrekt

Hvis fejlloggen regelmæssigt siger „server reached pm.max_children“, begrænser puljen antallet af børn. Parallelisme og jeg øger den moderat. Hvis 502/504 forekommer med høj swap-udnyttelse på samme tid, nulstiller jeg pm.max_children og sænker pm.max_requests. Hvis CPU'en stiger med lav RAM-udnyttelse, er det normalt forespørgsler eller PHP-logik, der blokerer; jeg optimerer databasen og cachelagringen. Hvis forespørgsler sidder fast, hjælper en strengere request_terminate_timeout og loganalyse med tidsstempler. Jeg tjekker iøjnefaldende toppe i forhold til cronjobs, søgeindeks og administratorhandlinger.

FPM-status og slowlog: præcis diagnose

Jeg aktiverer Status per pulje (pm.status_path) og læse nøgletal som f.eks. aktive processer, max antal børn nået, lyttekø og maks. lyttekø af. En permanent voksende listekø viser tydeligt: for få børn eller blokerende backends. Jeg har også sat request_slowlog_timeout (f.eks. 3-5s) og en slowlog-sti. Det er sådan, jeg ser stakspor af anmodninger, der trækker ud - ofte eksterne HTTP-kald, komplekse WooCommerce-forespørgsler eller billedmanipulationer. Med catch_workers_output advarsler fra arbejderne opsamles i logfilerne. På baggrund af disse data beslutter jeg, om mere parallelisme hjælper, eller om jeg skal løse flaskehalse i koden/DB'en.

Overvågning: 3-5 dages ren evaluering

Efter tuning observerer jeg belastningstoppe over flere dage, fordi kortvarig udsving bedrager. Jeg logger RAM, swap, 502/504, TTFB og antallet af aktive processer i FPM-status. Under 80 procent RAM-udnyttelse uden swap og uden køer har jeg ret. Hvis der opstår flaskehalse under handlinger som checkout, søgning eller import, justerer jeg specifikt pm.max_children og pm.max_requests. Hvert trin udføres i små justeringer og med en ny måling.

Hukommelsesberegning i detaljer: RSS, PSS og delt hukommelse

Procesvariablen er vanskelig: RSS (Resident Set Size) indeholder også delte segmenter som OPcache og biblioteker. Jeg overvurderer derfor hurtigt RAM-forbruget, hvis jeg bare beregner „RSS × Children“. Bedre er det at PSS-view (Proportional Set Size), som fordeler delt hukommelse retfærdigt på tværs af processer - værktøjer som smem hjælper her. Beregningen omfatter OPcache (f.eks. 256 MB + strenge), APCu (f.eks. 64-128 MB) og masterprocessen. PHP memory_limit er ikke et gennemsnit, men den øvre grænse pr. anmodning; der kan forekomme individuelle toppe, men det er gennemsnitsværdien, der tæller. Jeg planlægger en buffer, så spidsbelastninger, udrulninger og cronjobs ikke straks udløser swaps, og lader pm.max_anmodninger for at begrænse opblæsning af hukommelsen.

Reducer WordPress-specifik belastning

Jeg reducerer først PHP-belastningen, før jeg øger antallet af børn yderligere, fordi en hurtigere cache-hitrate sparer realtid. RAM. Full-page caches reducerer drastisk PHP-anmodninger, hvilket skaber kapacitet til checkout, søgning og administration. OPcache med memory_consumption på 256 MB accelererer bytekode og aflaster poolen. I praksis holder jeg PHP memory_limit på 256M, så individuelle plugins ikke sløver serveren. Mere indsigt i flaskehalse kan findes i guiden PHP-Worker som flaskehals.

Database- og cache-backends i balance

Hver PHP-arbejder genererer potentielt en Databaseforbindelse. Hvis jeg øger pm.max_children, øges den samtidige DB-belastning også. Jeg tjekker derfor MySQL/MariaDB: max_forbindelser, buffer (innodb_buffer_pool_size) og forespørgselsplanlæggeren. Redis/Memcached skal følge med parallelt. maxclients, hukommelsesgrænse og ventetider. En WordPress-instans med 20 aktive børn kan nemt mætte DB'en, hvis flere dyre forespørgsler kører parallelt. Det er derfor, jeg tuner DB'en (indekser, langsomme forespørgsler) og sætter den til Vedvarende objekt-caches, før jeg frigiver flere børn. Det øger gennemstrømningen uden at overbelaste backend.

WooCommerce, Cron og Admin: særlige tilfælde

Butikker genererer flere samtidige dynamiske forespørgsler, hvilket er grunden til, at jeg bruger noget Luft med pm.max_children. Samtidig har jeg en tendens til at sænke pm.max_requests for løbende at reducere opblødning af hukommelsen. For import og cronjobs planlægger jeg ekstra budget eller udfører opgaver uden for spidsbelastningsperioder. Administratorområdet får ofte spidsbelastninger med kort varsel; caching giver mindre beskyttelse her, så effektiv poolkontrol tæller. Hvis der er tegn på køer, øger jeg i små trin og overvåger målingerne umiddelbart efter.

Containere, vCPU-kvoter og OOM-fælder

I containere og VM'er er der fokus på effektiv RAM-grænse (cgroups), ikke på værten. Jeg beregner derfor pm.max_children ud fra den tildelte grænse og ikke ud fra „free -h“. Container OOMs er nådesløse - kernen afslutter processer hårdt. CPU-kvoter tæller også med: Flere børn hjælper ikke, hvis 1-2 vCPU'er begrænser computertiden. Som en tommelfingerregel skalerer jeg IO-tunge WordPress-arbejdsbelastninger til omkring 2-4× antallet af vCPU'er; over dette øges kontekstskift, men ikke den reelle gennemstrømning. I orkestrerede miljøer udruller jeg ændringer konservativt, observerer pod-genstarter og holder øje med readiness/liveness probes, så korte opvarmningsfaser af FPM ikke tæller som fejl.

Fejlkilder, der ofte overses

Mange problemer stammer ikke fra poolen, men fra Plugins, der multiplicerer anmodninger eller genererer lange processer. Indekserede søgninger, brudte crawler-regler og overdrevne heartbeat-intervaller øger belastningen. Derfor tjekker jeg altid logs, query monitor og caching-headers først. Hvis belastningen kun forekommer med bestemte URL'er, tolker jeg det som en indikation på flaskehalse i plugins eller skabeloner. Først når disse problemer er løst, skalerer jeg Children yderligere.

Forståelse af sessioner, admin AJAX og låse

WordPress/plugins arbejder delvist med Sessioner. Filbaserede sessionslåse kan serialisere anmodninger - en enkelt langsom anmodning blokerer resten af det samme sessions-ID. Jeg holder sessionsforbruget nede og tjekker, om admin AJAX bursts (wp-admin/admin-ajax.php) fyres af unødigt ofte. Heartbeat skal drosles fornuftigt ned, ellers genererer det belastning uden merværdi. Hvis der opstår låse eller lange filadgange, hjælper det ikke med mere parallelitet; her hjælper caching, hurtigere storage I/O eller en anden sessionshåndtering. I logfiler genkender jeg sådanne mønstre fra mange lignende forespørgsler, der starter på samme tid med usædvanligt lange køretider.

Et overblik over timeouts for Nginx, Apache og FastCGI

Webserveren sætter også grænser, som jeg er nødt til at harmonisere med FPM-værdierne, ellers går de i stå. Indstilling. Med Nginx er jeg opmærksom på fastcgi_read_timeout og tilstrækkeligt med arbejdsprocesser. Under Apache tjekker jeg mpm_event, keepalive-indstillinger og proxy-timeouts. Hvis disse grænser ikke er korrekte, rapporterer brugerne timeouts, selv om FPM stadig har kapacitet. Standardiserede tidsbudgetter holder stien fra klienten til PHP konsistent.

Udrulningsstrategi, test og drift

Jeg udruller ændringer til pm.max_children trin for trin og tester dem under reel belastning. En genindlæsning af FPM (graceful) overtager konfigurationer uden at afbryde forbindelsen. Før større spring simulerer jeg spidsbelastninger (f.eks. salgsstart) og observerer lyttekø, CPU, RAM, 95.-99. percentil af latenstid og fejlrater. Jeg dokumenterer de antagelser, der er gjort, så senere teammedlemmer forstår, hvorfor en værdi er valgt på denne måde. Jeg indstiller alarmer for: swap > 0, „max children reached“ i status, stigende 502/504 og DB-latency. Dette sikrer, at platformen forbliver stabil, selv måneder senere, når trafikken og plugin-mixet ændres.

Kort opsummeret

Forkert indstillet PHP-FPM-børn gør WordPress langsommere, enten i køer eller i RAM-grænsen. Jeg bestemmer processtørrelsen, reserverer hukommelse til systemtjenester og sætter pm.max_children med buffer. Derefter kontrollerer jeg pm.max_requests, request_terminate_timeout og tilstanden pm = dynamisk eller statisk i henhold til belastningsprofilen. Caching, OPcache og rene plugins reducerer mærkbart antallet af PHP-anmodninger. Hvis du implementerer disse trin konsekvent, vil du holde siderne responsive og serveren pålidelig.

Aktuelle artikler