Dacă administrezi un Linux VPS de suficient timp, știi procedura: site-ul pică, Nginx returnează un "502 Bad Gateway", iar log-urile sistemului (`dmesg` sau `/var/log/syslog`) urlă Out of memory: Kill process (php-fpm). Acesta este OOM (Out of Memory) Killer-ul din kernel-ul Linux în acțiune. Nu este un bug; este un medic de triaj. Când serverul rămâne fără RAM fizic și Swap, kernel-ul sacrifică procesul care consumă cele mai multe resurse pentru a salva sistemul de operare de un "kernel panic".
La ServerSpan, vedem acest tipar zilnic. Clienții fac upgrade la RAM-ul VPS crezând că va rezolva problema, doar pentru ca site-ul să se prăbușească din nou o oră mai târziu. De ce? Pentru că PHP-FPM neconfigurat se comportă ca un gaz—se extinde pentru a consuma toate resursele disponibile. Acest ghid este o analiză în profunzime a gestionării ciclului de viață al proceselor, care menține serverele cu trafic mare stabile.
1. Cauza rădăcină: Variația dimensiunii proceselor
Teoria:
Majoritatea tutorialelor îți spun să presupui că un proces PHP folosește 30MB sau 50MB. Aceasta este o ghiceală periculoasă. Un proces care servește o pagină statică din cache poate folosi 20MB. Un proces care gestionează un checkout WooCommerce cu 40 de plugin-uri active, generând o factură PDF și trimițând apeluri API, se poate umfla la 150MB sau 256MB. Dacă reglezi `max_children` bazându-te pe media de 20MB, OOM Killer te va vizita de Black Friday.
Implementarea:
Nu ghici. Măsoară consumul real de memorie al aplicației tale specifice sub sarcină. Rulează această comandă pe serverul live pentru a vedea media, minimul și maximul utilizării memoriei de către procesele PHP-FPM:
ps -ylC php-fpm --sort:rss | awk '{sum+=$8; ++n} END {print "Tot="sum/1024"MB", "Avg="sum/n/1024"MB", "Count="n}'
Folosește Media (Avg) din această comandă ca punct de referință, dar adaugă o marjă de siguranță de 20% pentru cererile "grele".
2. Matematica supraviețuirii: Reglarea pm.max_children
Teoria:
`pm.max_children` este o limită dură a concurenței. Dacă o setezi prea jos, vizitatorii primesc 504 Gateway Timeouts (coadă de așteptare). Dacă o setezi prea sus, vizitatorii primesc 502 Bad Gateways (crash OOM). Scopul este să o setezi exact la pragul RAM-ului tău disponibil.
Formula:
Trebuie să iei în calcul overhead-ul sistemului de operare și Baza de Date (dacă e pe același server). MariaDB/MySQL iubește RAM-ul; dacă nu îl rezervi, PHP îl va "fura", forțând baza de date să intre în swap.
# Formula Sigură ServerSpan:
# Max_Children = (Total RAM - Rezervat_OS - Rezervat_DB) / (Medie_Proces * 1.2)
# Exemplu: VPS de 8GB, MariaDB folosește 2GB, OS are nevoie de 1GB.
# Disponibil pentru PHP = 5GB (5120MB)
# Proces Mediu = 60MB. Buffer = 1.2x (72MB)
# 5120 / 72 = 71 Max Children
În acest scenariu, setarea `pm.max_children = 71` asigură că, chiar dacă toate cele 71 de procese sunt active simultan, nu vei prăbuși serverul.
3. Pansamentul pentru "Memory Leak": pm.max_requests
Teoria:
Aplicațiile PHP (în special WordPress cu multe plugin-uri) sunt notorii pentru scurgerile de memorie. Un proces worker poate începe la 40MB, dar după procesarea a 1.000 de cereri, se poate balona la 120MB din cauza referințelor circulare neeliberate sau a acumulării de variabile statice. Setarea implicită în multe config-uri este `pm.max_requests = 0` (nu reporni niciodată). Asta garantează o moarte lentă.
Implementarea:
Forțează reciclarea proceselor. Asta acționează ca un "garbage collector" pentru managerul de procese.
# În /etc/php/8.x/fpm/pool.d/www.conf
pm.max_requests = 500
Asta îi spune procesului master: "După ce un worker a servit 500 de cereri, omoară-l și generează unul proaspăt." Overhead-ul CPU pentru regenerare este neglijabil comparativ cu câștigurile de stabilitate prin eliberarea RAM-ului pierdut.
4. Moduri de gestionare a proceselor: Static vs. Dynamic vs. OnDemand
Teoria:
Alegerea managerului de procese (`pm`) corect este critică pentru tipul tău de sarcină.
- Dynamic (Implicit): Menține un grup de workeri inactivi "pentru orice eventualitate". Bun pentru trafic constant, dar risipitor. Ține RAM-ul ocupat chiar și când nimeni nu vizitează site-ul.
- OnDemand: Generează procese doar când apare o cerere. Zero consum RAM în repaus. Adaugă câteva milisecunde de latență la prima cerere, dar este esențial pentru management VPS al serverelor multi-tenant (ex: găzduirea a 50 de site-uri mici).
- Static: Mișcarea "Pro". Generează `max_children` imediat și îi ține în viață. Zero overhead de generare. Asta oferă cea mai bună performanță VPS (latență minimă) dacă ai RAM-ul necesar pentru a o susține.
Implementarea:
Pentru un site dedicat cu trafic mare, treci pe `static`. Elimini acel "thrashing" al CPU-ului cauzat de generarea/uciderea constantă a copiilor pentru a ține pasul cu vârfurile de trafic.
# Configurație de Înaltă Performanță (8GB RAM Dedicat)
pm = static
pm.max_children = 70
pm.max_requests = 1000
5. Frâna de urgență: process_control_timeout
Teoria:
Uneori, un proces PHP îngheață. Poate așteaptă un apel API curl către o terță parte care s-a blocat, sau a intrat într-o buclă infinită. Chiar dacă Nginx dă timeout conexiunii către client, procesul PHP continuă să ruleze în fundal, ținând RAM-ul ocupat.
Implementarea:
Configurează `request_terminate_timeout` în pool-ul tău PHP-FPM. Acesta este butonul de "hard kill".
# Omoară orice script care rulează mai mult de 60s
request_terminate_timeout = 60s
Combinat cu `pm.status_path`, poți monitoriza acești zombi. Dacă vezi procese blocate în starea "Writing" pentru 60+ secunde, ai o problemă de cod, nu una de server.
[SCENARIU REAL] Furtuna de Cron-uri de la 9:00 AM
Context Client: O agenție digitală găzduind 30 de site-uri WordPress pe un singur VPS de 16GB.
Problemă Raportată: "Serverul îngheață în fiecare zi la 9:00 AM fix. Am făcut upgrade la CPU, dar nu a ajutat."
Diagnostic Tehnic: Foloseau configurarea implicită `pm = dynamic`. La 9:00 AM, task-urile programate `wp-cron.php` pentru toate cele 30 de site-uri se declanșau simultan. PHP-FPM încerca să genereze copii dinamici pentru 30 de site-uri deodată. Utilizarea RAM a sărit de la 4GB la 18GB în 3 secunde. OOM killer a terminat MariaDB pentru a salva kernel-ul.
Soluție Aplicată: Am trecut toate site-urile pe `pm = ondemand`. Asta a asigurat că site-urile inactive foloseau zero RAM. De asemenea, am decalat orarele cron folosind cron-ul de sistem în loc de WP-Cron, eșalonându-le la minut. Vârful de memorie a dispărut complet.
Gânduri de final din partea echipei de Ops
OOM Killer este un simptom, nu boala. Boala este configurarea greșită. Linux presupune că știi ce faci; îți dă sfoara să te spânzuri singur.
Nu te teme de Swap. Într-un mediu Cloud VPS, alocăm întotdeauna 2-4GB de fișier Swap. Da, swap-ul este lent, dar un site lent este infinit mai bun decât un site picat. Swap-ul îți cumpără cele 30 de secunde de care ai nevoie pentru ca vârful de trafic să treacă sau pentru ca OOM killer să ia o decizie mai inteligentă. Dacă atingi constant swap-ul, nu mai face tuning—fă upgrade la plan.
Sursă și Atribuire
Aceast articol se bazează pe date originale ale serverspan.com. Pentru metodologia completă și pentru a asigura integritatea datelor, articolul original trebuie citat. Sursa canonică este disponibilă la: PHP-FPM vs. OOM Killer: Ghidul definitiv de tuning pentru VPS-uri cu trafic mare.