Optimizarea PHP-FPM pentru performanțe ridicate

PHP este peste tot și este probabil cea mai largă limbă desfășurată pe Internet.


Cu toate acestea, nu este cunoscut exact pentru capacitățile sale de înaltă performanță, mai ales când vine vorba de sisteme extrem de concurente. Și acesta este motivul pentru care pentru astfel de cazuri de utilizare specializată, limbi precum Node (da, știu, nu este o limbă), Go și Elixir preiau.

Acestea fiind spuse, există o mulțime de lucruri pe care le poți face pentru a îmbunătăți performanța PHP pe serverul tău. Acest articol se concentrează pe partea php-fpm a lucrurilor, care este modul natural de a configura pe serverul dvs. dacă utilizați Nginx.

În cazul în care știi ce este php-fpm, nu ezitați să sari la secțiunea despre optimizare.

Ce este php-fpm?

Nu mulți dezvoltatori sunt interesați de DevOps în ceea ce privește lucrurile și chiar printre cei care fac asta, foarte puțini știu ce se întâmplă sub capotă. Interesant este că atunci când browserul trimite o solicitare către un server care rulează PHP, nu PHP este cel care formează primul punct de contact; în schimb, este serverul HTTP, dintre care principalele sunt Apache și Nginx. Aceste „servere web” trebuie apoi să decidă cum să vă conectați la PHP și să transmiteți tipul de solicitare, datele și anteturile la acesta.

Ciclul cerere-răspuns în cazul PHP (Credit imagine: ProinerTech)

În aplicațiile PHP moderne, partea „găsi fișierul” de mai sus este index.php, la care serverul este configurat pentru a delega toate cererile către.

Acum, a evoluat exact cum se conectează serverul web la PHP, iar acest articol ar exploda în lungime dacă ar fi să intrăm în tot ceea ce este neplăcut. Dar aproximativ vorbind, în perioada în care Apache a dominat drept serverul web la alegere, PHP a fost un modul inclus în server.

Deci, de fiecare dată când a fost primită o solicitare, serverul va începe un nou proces, care va include automat PHP, și îl va executa. Această metodă a fost numită mod_php, scurt pentru „php ca modul”. Această abordare a avut limitele sale, pe care Nginx le-a depășit cu php-fpm.

În php-fpm responsabilitatea administrării PHP, procesele aparțin programului PHP din server. Cu alte cuvinte, serverul web (Nginx, în cazul nostru), nu-i pasă de unde este PHP și cum este încărcat, atât timp cât știe să trimită și să primească date de la acesta. Dacă doriți, vă puteți gândi la PHP în acest caz ca la un alt server în sine, care gestionează unele procese PHP copil pentru cererile primite (deci, avem cererea care ajunge la un server, care a fost primit de un server și transmis pe un server – destul de nebun! :-P).

Dacă ați făcut configurații Nginx sau chiar ați invocat-o, veți găsi ceva de genul:

locație ~ \ .php $ {
try_files $ uri = 404;
fastcgi_split_path_info ^ (. + \. php) (/.+) $;
fastcgi_pass unix: /run/php/php7.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;
}

Linia care ne interesează este următoarea: fastcgi_pass unix: /run/php/php7.2-fpm.sock; ceea ce îi spune lui Nginx să comunice cu procesul PHP prin priza numită php7.2-fpm.sock. Așadar, pentru fiecare cerere primită, Nginx scrie date prin acest fișier și, la primirea ieșirii, o trimite înapoi browserului.

Încă o dată, trebuie să subliniez că aceasta nu este cea mai completă sau cea mai exactă imagine a ceea ce se întâmplă, ci este complet exactă pentru majoritatea sarcinilor DevOps.

Cu acest aspect, să recapitulăm ceea ce am învățat până acum:

  • PHP nu primește în mod direct cereri trimise de browsere. Serverele Web ca Nginx le interceptă mai întâi.
  • Serverul web știe să se conecteze la procesul PHP și transmite toate datele solicitării (lipiți literalmente totul) la PHP.
  • Când PHP a terminat să-și facă partea, trimite răspunsul înapoi la serverul web, care îl trimite înapoi clientului (sau browserului, în majoritatea cazurilor).

Sau grafic:

Cum funcționează PHP și Nginx (Credit imagine: DataDog)

Excelent până acum, dar acum vine întrebarea de milioane de dolari: care este exact PHP-FPM?

Partea „FPM” din PHP înseamnă „Fast Process Manager”, care este doar un mod fantezist de a spune că PHP-ul care rulează pe un server nu este un singur proces, ci mai degrabă unele procese PHP care sunt generate, controlate și ucise. oprit de acest manager de proces FPM. Acest manager de proces este cel pe care serverul web le transmite cererilor.

PHP-FPM este o întreagă gaură de iepure în sine, așa că nu ezitați să explorați dacă doriți, dar pentru scopurile noastre, această multă explicație o va face. ��

De ce să optimizezi php-fpm?

Atunci de ce să vă faceți griji pentru tot acest dans atunci când lucrurile merg bine? De ce nu lăsați lucrurile așa cum sunt.

În mod ironic, acesta este tocmai sfatul pe care îl dau pentru majoritatea cazurilor de utilizare. Dacă configurarea dvs. funcționează bine și nu are cazuri de utilizare extraordinare, utilizați setările implicite. Cu toate acestea, dacă încercați să depășiți dimensiunea dincolo de o singură mașină, eliminarea maximului de la una este esențială, deoarece poate reduce facturile serverului la jumătate (sau chiar mai mult!).

Un alt lucru de realizat este că Nginx a fost construit pentru a gestiona sarcini uriașe de muncă. Este capabil să gestioneze mii de conexiuni în același timp, dar dacă nu este același lucru pentru configurarea PHP, vei pierde resurse, deoarece Nginx va trebui să aștepte ca PHP să termine cu procesul curent și să accepte în continuare, în mod extrem de negativ, orice avantaje pe care Nginx a fost construit să le ofere!

Așadar, cu asta, ne uităm la ce anume vom schimba atunci când încercăm să optimizăm php-fpm.

Cum să optimizați PHP-FPM?

Locația fișierului de configurare pentru php-fpm poate diferi pe server, astfel încât va trebui să faceți unele cercetări pentru localizarea acestuia. Puteți utiliza comanda find dacă este pe UNIX. Pe Ubuntu, calea este /etc/php/7.2/fpm/php-fpm.conf. 7.2, desigur, este versiunea PHP pe care o execut.

Iată cum arată primele rânduri ale acestui fișier:

;;;;;;;;;;;;;;;;;;;;;
; Configurare FPM;
;;;;;;;;;;;;;;;;;;;;;

; Toate căile relative din acest fișier de configurare sunt relative la instalarea PHP
; prefix (/ usr). Acest prefix poate fi schimbat dinamic folosind
; Argumentul „-p” din linia de comandă.

;;;;;;;;;;;;;;;;;;
; Opțiuni globale;
;;;;;;;;;;;;;;;;;;

[global]
; Fișier Pid
; Notă: prefixul implicit este / var
; Valoare implicită: niciuna
pid = /run/php/php7.2-fpm.pid

; Fișier jurnal de eroare
; Dacă este setat la "syslog", jurnalul este trimis la syslogd în loc să fie scris
; într-un fișier local.
; Notă: prefixul implicit este / var
; Valoare implicită: log / php-fpm.log
eroare_log = /var/log/php7.2-fpm.log

Câteva lucruri ar trebui să fie imediat evidente: linia pid = /run/php/php7.2-fpm.pid ne spune ce fișier conține ID-ul procesului php-fpm.

De asemenea, vedem că /var/log/php7.2-fpm.log este locul în care php-fpm va stoca jurnalele sale.

În acest fișier, adăugați alte trei variabile de acest fel:

Emergency_restart_threshold 10
urgent_restart_interval 1m
process_control_timeout 10s

Primele două setări sunt de precauție și spun procesului php-fpm că dacă zece procese copil eșuează într-un minut, procesul principal php-fpm ar trebui să repornească.

S-ar putea ca acest lucru să nu pară robust, dar PHP este un proces de scurtă durată, care scurge memoria, așa că repornirea procesului principal în cazurile de defecțiune mare poate rezolva o mulțime de probleme.

A treia opțiune, process_control_timeout, spune procesului copil să aștepte acest timp mult timp înainte de a executa semnalul primit de la procesul părinte. Acest lucru este util în cazurile în care procesele copil sunt în mijlocul a ceva când procesele părinte trimit un semnal KILL, de exemplu. Cu zece secunde la îndemână, vor avea șanse mai bune de a-și termina sarcinile și de a ieși cu grație.

În mod surprinzător, aceasta nu este carnea configurației php-fpm! Acest lucru se datorează faptului că pentru a răspunde cererilor web, php-fpm creează un nou grup de procese, care va avea o configurație separată. În cazul meu, numele grupului s-a dovedit a fi www, iar fișierul pe care doream să îl modifice a fost /etc/php/7.2/fpm/pool.d/www.conf.

Să vedem cum începe acest fișier:

; Porniți un nou grup numit „www”.
; variabila $ pool poate fi utilizată în orice directivă și va fi înlocuită de
; numele piscinei („www” aici)
[Www]

; Prefixul piscinei
; Se aplică numai în următoarele directive:
; – ‘access.log’
; – „slowlog”
; – „asculta” (unixsocket)
; – „chroot”
; – ‘chdir’
; – ‘php_values’
; – ‘php_admin_values’
; Când nu este setat, se aplică prefixul global (sau / usr).
; Notă: Această directivă poate fi, de asemenea, relativă la prefixul global.
; Valoare implicită: niciuna
; prefix = / path / to / pools / $ pool

; Unix utilizator / grup de procese
; Notă: Utilizatorul este obligatoriu. Dacă grupul nu este setat, grupul utilizatorului implicit
; va fi folosit.
utilizator = www-data
group = www-data

O privire rapidă la sfârșitul fragmentului de mai sus rezolvă ghicitul despre motivul pentru care procesul serverului rulează ca date www. Dacă întâmpinați probleme legate de permisiunea fișierului atunci când configurați site-ul dvs. web, ați schimbat probabil proprietarul sau grupul directorului în date www, permițând astfel procesului PHP să poată scrie în fișiere jurnal și să încărce documente etc..

În cele din urmă, ajungem la sursa problemei, setarea managerului de proces (pm). În general, veți vedea valorile implicite ca fiind așa:

pm = dinamic
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200

Deci, ce înseamnă „dinamic”Aici înseamnă? Cred că documentele oficiale explică cel mai bine acest lucru (adică, acesta ar trebui să facă deja parte din fișierul pe care îl editați, dar l-am reprodus aici doar în cazul în care nu este):

; Alegeți modul în care managerul de proces va controla numărul de procese copil.
; Valori posibile:
; static – un număr fix (pm.max_children) de procese copil;
; dinamic – numărul de procese copil sunt setate dinamic pe baza
; urmând directive. Cu acest proces de gestionare, va exista
; întotdeauna cel puțin 1 copii.
; pm.max_children – numărul maxim de copii care poate
; fii viu în același timp.
; pm.start_servers – numărul de copii creat la pornire.
; pm.min_spare_servers – numărul minim de copii aflați în „inactiv”
; starea (așteptarea procesării). Dacă numărul
; a proceselor „idle” este mai mică decât aceasta
; numărul apoi vor fi creați unii copii.
; pm.max_spare_servers – numărul maxim de copii aflați în „inactiv”
; starea (așteptarea procesării). Dacă numărul
; a proceselor „idle” este mai mare decât aceasta
; numărul apoi unii copii vor fi uciși.
; ondemand – nu sunt creați copii la pornire. Copiii vor fi furcați când
; cererile noi se vor conecta. Se utilizează următorul parametru:
; pm.max_children – numărul maxim de copii care
; poate fi viu în același timp.
; pm.process_idle_timeout – Numărul de secunde după care
; un proces inactiv va fi ucis.
; Notă: Această valoare este obligatorie.

Deci, vedem că există trei valori posibile:

  • Static: Un număr fix de procese PHP va fi menținut indiferent de situație.
  • Dinamic: Trebuie să specificăm numărul minim și maxim de procese pe care php-fpm le va menține în viață la un moment dat.
  • la cerere: Procesele sunt create și distruse, la cerere.

Deci, cum contează aceste setări?

În termeni simpli, dacă aveți un site web cu trafic redus, setarea „dinamică” este o pierdere de resurse de cele mai multe ori. Presupunând că aveți pm.min_spare_servers setate la 3, trei procese PHP vor fi create și întreținute chiar și atunci când nu există trafic pe site-ul web. În astfel de cazuri, „ondemand” este o opțiune mai bună, permițând sistemului să decidă când să lanseze noi procese.

Pe de altă parte, site-urile web care gestionează cantități mari de trafic sau trebuie să răspundă rapid vor fi pedepsite în această setare. Crearea unui nou proces PHP, făcându-l să facă parte dintr-un pool și să îl monitorizeze, este un aer suplimentar care este cel mai bine evitat.

Utilizarea pm = static stabilește numărul de procese copil, permițând resurselor maxime ale sistemului să fie utilizate pentru a răspunde cererilor și nu pentru a gestiona PHP. Dacă mergeți pe acest traseu, aveți grijă că acesta are ghidurile și capcanele sale. Un articol destul de dens, dar extrem de util despre el este aici.

Cuvinte finale

Deoarece articolele despre performanța web pot provoca războaie sau pot servi la confuzia oamenilor, simt că câteva cuvinte sunt în regulă înainte de a închide acest articol. Reglarea performanței este la fel de mult despre ghicitul și artele întunecate, ci despre cunoașterea sistemului.

Chiar dacă știți toate setările php-fpm de la inimă, succesul nu este garantat. Dacă nu aveți niciun indiciu despre existența php-fpm, nu trebuie să pierdeți timpul îngrijorat. Continuați să faceți ceea ce faceți deja și continuați.

În același timp, evitați sfârșitul de a fi un junkie performant. Da, puteți obține o performanță și mai bună prin recompilarea PHP de la zero și prin eliminarea tuturor modulelor pe care nu le veți folosi, dar această abordare nu este suficient de generoasă în mediile de producție. Întreaga idee de a optimiza ceva este să aruncați o privire dacă nevoile dvs. diferă de valorile implicite (pe care rareori le fac!) Și să faceți modificări minore, după cum este necesar.

Dacă nu sunteți gata să alocați timp optimizării serverelor dvs. PHP, atunci puteți lua în considerare utilizarea unei platforme de încredere cum ar fi Kinsta care se ocupă de optimizarea performanței și de securitate.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map