Ojämn CPU-belastning i WordPress uppstår ofta på grund av dåligt konfigurerade wordpress cronjobs, som startar som bakgrundsprocesser varje gång en sida öppnas och därmed orsakar toppar. Jag visar hur dessa triggers förlänger TTFB, binder PHP-arbetare och skapar latenser – och hur du med system-cron, intervaller och prioritering återgår till jämnare Last kommer.
Centrala punkter
Följande översikt sammanfattar de viktigaste aspekterna innan jag går in på djupet och förklarar konkreta steg. Jag håller listan kort så att fokus ligger på Åtgärd och effekten ligger.
- WP-Cron utlöses vid sidvisningar och genererar oförutsägbar belastning.
- PHP-processer samlas vid trafik och saktar ner TTFB.
- System cron frikopplar uppgifter från besökarströmmen.
- Intervaller och prioriteringar utjämnar CPU-toppar.
- Övervakning upptäcker flaskhalsar och felaktiga händelser.
Vad WordPress-cronjobs verkligen gör – och var belastningen kommer ifrån
WordPress använder ett pseudo-cron-system: När det anropas triggas wp-cron.php via POST, kontrollerar förfallna händelser och startar uppgifter som publiceringar, uppdateringskontroller, sparande av utkast via Heartbeat och databasrensning – varje händelse kostar CPU-tid. Denna metod låter bekväm, men orsakar okontrollerbara triggers, eftersom besök avgör exekveringen och inte en planerbar timer. Om flera anrop sammanfaller startas parallella PHP-processer som konkurrerar om arbetare. Multisite-uppsättningar förstärker effekten, eftersom varje undersida har sin egen händelsestack och därmed ökar antalet kontroller [1]. Den som vill fördjupa sig i sammanhanget hittar gedigna grunder under Förstå WP-Cron, men kärnbudskapet kvarstår: besökarstyrning är inte lämpligt som ett tillförlitligt klockgenerator.
Den egentliga bromsen: parallella PHP-processer genom wp-cron.php
Varje Cron-trigger startar en separat PHP-process som binder en arbetare och därmed den tillgängliga beräkningstid för äkta sidrenderingar. Om triggarna hopar sig ökar väntetiden på en ledig arbetare, TTFB förlängs och den första byten anländer senare till webbläsaren [2]. Mätningar visade en fördröjning på upp till 800 millisekunder, vilket belastar Core Web Vitals och dämpar den organiska synligheten [3]. Delad hosting eller snäva PHP-FPM-inställningar förvärrar effekten, eftersom max_children snabbt nås och processer hamnar i köer. Särskilt vid butikstoppar eller kampanjer kan detta bli en ond cirkel: Mer trafik genererar fler cron-kontroller, som i sin tur blockerar rendering och därmed Laddningstider sträcka [1][2].
Hantera caching, CDN och loopback-fällor på rätt sätt
WP-Cron använder som standard en intern Loopback-förfrågan till den egna domänen. Om det finns en aggressiv sidcache, ett CDN eller en Basic-Auth-spärr framför den kan anropet misslyckas eller vänta – Cron-körningar fastnar, upprepas och förlänger därmed CPU-bindningen. Jag ser därför till att /wp-cron.php inte cachas, inte är hastighetsbegränsad och är internt tillgänglig. System-Cron avhjälper denna sårbarhet eftersom den utan HTTP-Loopback kör PHP direkt. Om en proxy är uppkopplad kontrollerar jag dessutom om förfrågningar till 127.0.0.1 överföras korrekt och att ingen WAF-regel blockerar slutpunkten. Under underhållsfaser är det viktigt att antingen medvetet pausa Cron eller uttryckligen släppa igenom slutpunkten så att förfallna uppgifter inte „efterföljer“ som paket.
Identifiera och klassificera ojämn CPU-belastning
Typisk är belastningstoppar under rusningstider, som inte enbart kan förklaras med antalet besökare, utan också med cron-vågor från försenade händelser som staplas och avfyras samtidigt. Multisite-installationer multiplicerar belastningen, eftersom varje undersida hanterar cron-listor och kontrolleras vid besök – detta skapar korta men hårda toppar, som loggfilerna visar som kaskader av wp-cron.php-POSTs [1]. Plugins registrerar ofta egna händelser med för korta intervall, ibland var femte minut eller oftare, vilket med tio plugins snabbt summeras till dussintals kontroller per anrop. Var också uppmärksam på din PHP-arbetarbegränsning, eftersom fulla arbetare tvingar fram väntetider som användarna direkt märker. Den som läser dessa mönster förstår den ojämna kurvan som en följd av triggers, inte som oundviklig humör av trafiken.
Varför System Cron jämnar ut belastningen
Ett äkta system-Cron kopplar bort uppgifter från besökarströmmen och sätter en tydlig takt, till exempel var femte minut, varje timme eller varje dag – på så sätt blir utförandet planerbart och belastningen jämnt fördelad [1][6]. Besökare utlöser då inte längre cron-jobb, vilket avlastar TTFB och prioriterar rendering. Även vid låg trafik körs uppgifterna pålitligt, eftersom servern utför dem även om ingen besöker sidan. Detta hjälper uppdateringar, e-postmeddelanden eller index-pings att köras i tid och förhindrar att händelser „ligger kvar“ och avfyras senare som ett paket. På så sätt skapar jag en förutsägbar systembelastning, som inte varierar beroende på trafikens humör.
Steg för steg: Inaktivera WP-Cron och konfigurera system-Cron
Jag börjar med att stänga av den interna triggern i wp-config.php så att inga sidvisningar längre startar cronjobs. Lägg till följande rad och spara filen så att WordPress inte startar någon cron-kontroll vid rendering. Därefter skapar jag en ren crontab-regel som startar wp-cron.php cykliskt utan att generera onödig utdata. På så sätt körs jobbet tidsstyrd och avlastar konsekvent sidupprop. Resultatet: Rendering har prioritet, cronjobs har en egen klockfrekvens.
// wp-config.php define('DISABLE_WP_CRON', true);
# Crontab-exempel (var 5:e minut) */5 * * * * php -q /var/www/html/wp-cron.php > /dev/null 2>&1
WP-CLI istället för direkt PHP-anrop
För bättre kontroll ställer jag gärna in cron-körningen med WP-CLI . På så sätt kan jag utföra „endast förfallna“ händelser, logga mer detaljerat och bearbeta multisiter på ett målinriktat sätt. Dessutom förhindrar en låsning att flera körningar startar parallellt.
# WP-CLI: endast bearbeta förfallna händelser */5 * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html --quiet
# Med enkel låsning via flock (rekommenderas) */5 * * * * flock -n /tmp/wp-cron.lock /usr/local/bin/wp cron event run --due-now --path=/var/www/html --quiet
I multisite-miljöer kan jag på så sätt via --url= Gå igenom webbplatsen för webbplats eller låt webbplatserna rotera via en liten shell-loop. Detta förhindrar att 100 undersidor samtidigt slår samma takt och skapar belastningstoppar.
Intervall och prioriteringar: vilka uppgifter ska utföras när?
Inte alla uppgifter behöver utföras varje minut; jag prioriterar efter relevans och kostnad så att SEO-kritiska jobb får företräde och dyra arbeten flyttas till mindre trafikerade tider [1]. Fokus ligger på att skapa sitemaps, indexeringspings och cache-uppvärmning, följt av databasunderhåll och radering av transienter. Jag planerar säkerhetskopieringar under nattliga tidsfönster och väljer inkrementella metoder för att undvika I/O-toppar. Jag sammanfattar nyhetsbrevsköer eller importörer och låter dem köras i fasta tidsluckor istället för att kontrollera dem vid varje sidbesök. Denna ordning säkerställer tydliga prioriteringar och förhindrar att korta pollintervall CPU täppa till.
| Uppgift | Rekommenderat intervall | CPU-påverkan | Ledtråd |
|---|---|---|---|
| Sitemap/indexerings-pings | varje timme till 1 gång per dag | låg | SEO-relevant; före cache-uppvärmning prioritera |
| Cache-uppvärmning | 1–2 gånger per dag | Medium | Gradera URL:er, inga fullständiga skanningar under högtrafik |
| Säkerhetskopior | på natten | hög | inkrementell; fjärrmål med bandbreddsbegränsning |
| Rensning av databas | dagligen eller veckovis | Medium | Revisioner/övergångar i block radera |
| E-postmeddelanden | varje timme/1×/dag | låg | Skapa batchar, använda kö |
Enkelkörningsmekanismer och rena lås
För att Cron-körningar inte ska överlappa varandra sätter jag vid sidan av flock även WordPress egna begränsningar. WP_CRON_LOCK_TIMEOUT definierar hur länge en körning förblir exklusiv. Om sidan är långsam eller om det finns långa jobb, ökar jag värdet måttligt så att ingen andra process startar för tidigt. Omvänt sänker jag det om jobben är korta och en hängning inte ska utlösa kaskader.
// wp-config.php – Låsningstid i sekunder (standard 60) define('WP_CRON_LOCK_TIMEOUT', 120);
Dessutom begränsar jag medvetet parallelliteten i plugins (batchstorlekar, steglängder, sömn mellan förfrågningar). På så sätt förhindrar jag att en cron-körning i sig genererar dussintals PHP-processer och ökar belastningskurvan.
Övervakning och analys: synliggöra flaskhalsar
Jag börjar med åtkomstloggarna och filtrerar POST-förfrågningar på wp-cron.php för att identifiera frekvens och tidsfönster; många korta intervall tyder på täta intervall eller blockerande händelser. Parallellt kontrollerar jag felloggarna för timeouts, låsningar och databasväntetider som påverkar cronjobs. I backend ger WP Crontrol insikt i registrerade händelser, deras hooks och planerade körtider; där raderar jag föråldrade eller hängande poster. För djupare insikt i transaktioner, frågetider och PHP-FPM-köer använder jag APM-verktyg för WordPress för att isolera hotspots. På så sätt kan jag hitta orsakerna istället för att bara dämpa symptomen, och kan målinriktat Åtgärder prioritera.
Mätbara mål och kort test på 10 minuter
Jag definierar tydliga målvärden: TTFB p95 för cachade sidor under 200–300 ms, för icke-cachade sidor under 800 ms; PHP-FPM-kö permanent nära 0; CPU utan toppar som går i mättnad. Den korta testet: inaktivera WP-Cron, ställa in system-Cron, bearbeta förfallna händelser en gång med WP-CLI, sedan kontrollera loggarna. På 10 minuter ser du om TTFB sjunker, PHP-kön krymper och om märkbara hooks (t.ex. uppdateringskontroller, importörer) står för huvuddelen. Justera sedan intervaller, batchstorlekar och takten tills kurvorna är stabila.
Tämja Heartbeat-API och plugin-händelser
Heartbeat-mekanismen uppdaterar sessioner och utkast, men genererar ofta onödiga förfrågningar i frontend. Jag begränsar den till admin-områden eller ställer in lämpliga intervall. Många plugins registrerar cronjobs med fabriksinställningar som är för täta. Här ställer jag in längre intervall och flyttar uppgifter till tider utanför rusningstid. I butiksinställningar begränsar jag lagerflöden och prissynkroniseringar till fasta tidsluckor istället för att pollera varje minut. För flöden och cache-uppvärmning använder jag batchlistor så att inte alla URL:er körs på en gång. Dessa ingrepp minskar förfrågningsfrekvensen och jämnar ut kurva helt klart.
Skalning: Från cronjobs till köer och arbetare
Vid hög trafik håller jag WP-Cron så liten som möjligt och flyttar beräkningsintensiva uppgifter till köer med dedikerade arbetare. Jobbköer fördelar belastningen på flera processer, kan utökas horisontellt och förhindrar att frontenden måste vänta. I container- eller orkestreringsuppsättningar skalar jag arbetare oberoende av PHP-FPM, vilket ger rendering och bakgrundsarbete separata resurser. Köer är särskilt lönsamma för importer, bildbearbetning, nyhetsbrevsbatcher och API-synkroniseringar. På så sätt förblir frontenden responsiv, medan bakgrundsjobb kontrolleras och planeringsbar kör.
WooCommerce, Action Scheduler och stora köer
WooCommerce erbjuder med Schemaläggning av åtgärder en egen kö som hanterar beställningsmejl, webhooks, prenumerationer och synkroniseringar. Just här finns det risk för CPU-toppar när tusentals åtgärder är „due“. Jag låter inte Runner köras när sidan öppnas, utan triggar den via System-Cron eller WP-CLI i fasta fönster. Jag ställer in batchstorlekar och parallellitet så att en körning inte blockerar databasen och PHP-FPM-Worker förblir fria. Importörer, bildåterställning och webhook-toppar fördelar jag på flera små genomgångar – hellre 10× kort än 1× i timmar med I/O-blockeringar.
Multisite-specifikationer: Balansera klockfrekvens per webbplats
I multisite-konfigurationer summeras belastningen eftersom varje webbplats har sin egen händelselista. Istället för att kontrollera allt var femte minut roterar jag webbplatserna: webbplatsgrupper med något förskjutna takter så att inte alla cron-listor körs samtidigt. För mycket aktiva webbplatser får kön oftare en plats, medan mindre aktiva webbplatser får det mer sällan. Resultatet är en jämnare CPU-kurva och mindre konkurrens om arbetare – med samma totala arbetsinsats.
Praktisk test: Konfiguration utan fallgropar
Jag kontrollerar först om DISABLE_WP_CRON är korrekt inställt, eftersom dubbla triggers (interna + externa) förvärrar belastningstoppar. Därefter kontrollerar jag crontab: korrekt sökväg, ingen onödig output, rimligt intervall och inga överlappningar med backup-fönster. I WP Crontrol rensar jag bort föråldrade hooks och ändrar täta intervall till realistiska cykler. Jag anpassar PHP-FPM-inställningarna till besökarprofilen så att PHP-Worker inte hela tiden ligger på maxgränsen. Slutligen spårar jag TTFB, svarstider och CPU för att tydligt se effekten av ändringarna. Pris.
Dimensionera PHP-FPM, OPCache och tidsgränser på rätt sätt
Den bästa Cron-strategin går om intet om PHP-FPM är för liten eller felaktigt klockad. Jag väljer pm=dynamisk eller . pm=på begäran beroende på trafikprofil och vidarebefordra pm.max_barn från det faktiska RAM-budgeten: Som tumregel RAM_för_PHP / genomsnittlig skriptförbrukning. Exempel: 2 GB budget och ~128 MB per process ger ~16 arbetare. pm.max_förfrågningar Jag sätter den på en moderat nivå (500–1000) för att begränsa läckor. begäran_avsluta_timeout begränsade avvikande jobb; en ren slowlog upptäcker frågeslingor och externa väntetider. En sund OPCache (tillräckligt med max_accelerated_files, minne_förbrukning, interned_strings_buffer) förhindrar kalla starter och sparar CPU per begäran – även för cron-körningar.
Objektcache och alternativhygien
En persistent objektcache (t.ex. Redis/Memcached) minskar databasbelastningen för cron-kontroller avsevärt. Det är viktigt att Hygien i wp_alternativ-Tabell: Alternativet cron får inte växa till flera megabyte, annars blir varje kontroll dyr. Jag tar bort föråldrade eller hängande händelser, minskar autoload-skräp och ställer in stora, sällan använda alternativ på autoload = nej. På så sätt minskar söktiderna och cron-listor kan utvärderas snabbare.
Finjustering: takt, ordning och resursbegränsningar
För webbplatser med toppar på förmiddagen schemalägger jag cache-uppvärmning till tidig natt och kör sitemaps strax före öppettiderna så att crawlers ser färska data. Dyra databasrensningar delar jag upp i mindre block för att minska låstider och förhindra toppar i sökningar. Stora exporter lägger jag till helgfönster, då det är mindre interaktion. När det är lämpligt begränsar jag parallella jobb så att inte flera cron-php-processer kämpar om I/O samtidigt. Denna finjustering säkerställer jämn genomströmning och bättre Svarstider.
Säkerhet: Skydda wp-cron.php mot extern åtkomst
Eftersom Cron ska aktiveras internt blockerar jag direkt extern åtkomst till /wp-cron.php. På så sätt förhindrar du missbruk, DDoS och oavsiktliga externa anrop. Tillåt endast lokala anrop (loopback eller CLI) och blockera allt annat. Detta minskar bruset i loggarna och skyddar PHP-arbetare.
# Nginx-exempel location = /wp-cron.php { allow 127.0.0.1; deny all; include fastcgi_params; fastcgi_pass php-fpm; }
# Apache-exempel Require ip 127.0.0.1
Vanliga orsaker till „spökbelastning“ från Cron
Mycket korta intervaller (1–5 minuter) för okritiska uppgifter är bland de största belastningsfaktorerna, särskilt i kombination med många plugins. Hängande händelser, som planeras om och om igen på grund av misslyckade körningar, skapar loopar som översvämmar loggarna. Låsningsproblem i databasen tvingar cronjobs till längre körtider, vilket ökar överlappningarna. Dessutom kan HTTP-blockeringar (t.ex. DNS eller Remote-API) artificiellt förlänga cron-körningar och binda arbetare. Den som känner till dessa mönster sparar mycket tid vid felsökning och minskar Toppar snabbt.
Kortfattat sammanfattat
Ojämn CPU-belastning i WordPress har ofta sitt ursprung i WP-Cron, som fungerar som en trigger vid sidvisningar och binder PHP-arbetare. Jag stänger av den interna triggern, ställer in en system-Cron, optimerar intervaller och prioriterar SEO-relevanta uppgifter så att rendering får företräde. Övervakning med loggar, WP Crontrol och APM-analyser visar mig felaktiga händelser, snäva takter och blockerande processer. För stora projekt flyttar jag beräkningsintensiva uppgifter till köer för att tydligt separera frontend- och bakgrundsjobb. Detta leder till en jämn belastning, kortare TTFB och märkbar snabbare Leverans – utan oväntade toppar.


