Indice dei contenuti dell'articolo:
PHP-FPM (o Fast Process Manager) offre diversi vantaggi rispetto a mod_php, con due dei più notevoli che è più flessibile da configurare e attualmente è la modalità preferita di esecuzione di PHP da molti nella comunità. Tuttavia, se stai utilizzando le impostazioni di configurazione predefinite del tuo gestore di pacchetti, probabilmente non ne otterrai il massimo.
In questo post, darò una breve panoramica su come migliorare le prestazioni di PHP-FPM, discutendo i tre tipi di gestori di processo di PHP-FPM e quale è il migliore da usare in quale circostanza.
PHP-FPM può utilizzare uno dei tre tipi di gestione dei processi :
- static (static)
- dynamic (dinamico)
- ondemand (su richiesta)
Diamo un’occhiata a ciò che ciascuno è un po’ in dettaglio andando ad individuare i pro ed i contro delle tre diverse modalità che possono comunque convivere tranquillamente nello stesso server.
Ad esempio potremmo avere nello stesso server, tre siti web di cui uno che gira in modalità static, uno ondemand ed uno dynamic senza alcun vincolo e con una totale separazione privilegi.
PHP in modalità Static
Statico garantisce che un numero fisso di processi figlio sia sempre disponibile per gestire le richieste degli utenti. Questo è impostato con pm.max_children . In questa modalità le richieste non devono attendere l’avvio di nuovi processi, il che lo rende l’approccio più veloce.
Supponendo che tu voglia usare la configurazione statica con 10 processi figlio sempre disponibili, dovresti configurarla /etc/php/7.2/fpm/pool.d/www.conf
(supponendo che tu stia usando il file di configurazione predefinito di PHP-FPM di Debian/Ubunut) come segue:
pm = static pm.max_children = 10
Per vedere se la modifica alla configurazione è stata efficace, dopo aver riavviato PHP-FPM, eseguire pstree -c -H <PHP-FPM process id> -S <PHP-FPM process id>
. Questo mostrerà che ci sono dieci processi disponibili, come nell’esempio seguente.
php-fpm7.2-+-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 `-php-fpm7.2
PHP in modalità Dynamic
In questa modalità, PHP-FPM gestisce dinamicamente il numero di processi figlio disponibili e garantisce che almeno un processo figlio sia sempre disponibile.
Questa configurazione utilizza cinque opzioni di configurazione; questi sono:
pm.max_children
: il numero massimo di processi figlio che possono essere generati.pm.start_servers
: il numero di processi figlio da avviare all’avvio di PHP-FPM.pm.min_spare_servers
: il numero minimo di processi figlio inattivi che PHP-FPM creerà. Ne vengono creati altri se sono disponibili meno di questo numero.pm.max_spare_servers
: Il numero massimo di processi figlio inattivi che PHP-FPM creerà. Se sono disponibili più processi figlio di questo valore, alcuni verranno eliminati.pm.process_idle_timeout
: il tempo di inattività, in secondi, dopo il quale un processo figlio verrà interrotto.
Ora arriva la parte divertente; come si calcolano i valori per ogni impostazione? Sebastian Buckpesch , propone la seguente formula:
Ambientazione | Valore |
---|---|
max_children | (RAM totale – Memoria utilizzata per Linux, DB, ecc.)/dimensione del processo |
start_server | Numero di core della CPU x 4 |
min_spare_servers | Numero di core della CPU x 2 |
max_spare_servers | Uguale astart_servers |
Dobbiamo anche impostare pm.process_idle_timeout
, che è il numero di secondi dopo i quali un processo inattivo verrà interrotto.
Diciamo che il nostro server ha due CPU, ciascuna con quattro core, e 8GB di RAM. Se assumiamo che Linux e i relativi demoni stiano utilizzando circa 2 GB (usare free -hl
per ottenere un valore più specifico), ciò ci lascia circa 6192 MB.
Ora, quanta memoria utilizza ciascun processo? Per calcolarlo, c’è uno script Python chiamato ps_mem.py . Dopo averlo eseguito, utilizzando sudo python ps_mem.py | grep php-fpm
, otterrai un output simile al seguente:
28.4 MiB + 33.8 MiB = 62.2 MiB php-fpm7.2 (11)
La prima colonna è la memoria privata. La seconda colonna è la memoria condivisa. La terza colonna è la RAM totale utilizzata. La quarta colonna è il nome del processo.
Da quanto sopra, puoi vedere che la dimensione del processo è 62,2 MiB. Quindi, inserendo tutte queste informazioni nella nostra formula, arriviamo a quanto segue:
# Round the result up. (8192 - 2000) / 62.2
Sulla base di ciò, arriviamo ai seguenti valori di impostazione:
Ambientazione | Valore |
---|---|
max_children | 100 |
start_server | 32 |
min_spare_servers | 16 |
max_spare_servers | 32 |
Lasceremo pm.process_idle_timeout
il valore predefinito di 10s
. Supponendo di essere soddisfatti di queste impostazioni, lo configureremmo come segue:
pm = dynamic pm.max_children = 100 pm.start_servers = 32 pm.min_spare_servers = 16 pm.max_spare_servers = 32 pm.max_requests = 200
Puoi anche utilizzare regolarmente gli strumenti di monitoraggio della memoria per monitorare la quantità di memoria utilizzata dall’applicazione. Ci sono una serie di opzioni disponibili per PHP, tra cui php-memprof.
PHP in modalità Ondemand
Il metodo ondemand avvia i processi fork di PHP-FPM quando vengono ricevute le richieste. Per configurare PHP-FPM in modalità ondemand, è necessario impostare i seguenti parametri:
pm.max_children
pm.process_idle_timeout
pm.max_requests
pm.max_requests
imposta il numero di richieste che ogni processo figlio deve eseguire prima del respawn. La documentazione suggerisce che questa impostazione è utile per aggirare le perdite di memoria.
Supponendo di utilizzare le stesse impostazioni di dynamic
, lo configureremmo come segue:
pm = ondemand pm.max_children = 100 pm.process_idle_timeout = 10s pm.max_requests = 200
Quale configurazione è giusta per te?
Onestamente? La risposta è: “ dipende ”, in quanto dipende sempre dal tipo di applicazioni che stai eseguendo. Tuttavia, ecco alcuni suggerimenti su quale configurazione scegliere.
Sito a basso traffico
Se hai un sito a basso traffico, come uno che ospita un pannello di controllo di back-end, come cPanel , usa ondemand. La memoria verrà salvata poiché i processi figlio verranno generati solo quando sono necessari e uccisi quando non sono più necessari. Poiché si tratta di un back-end, gli utenti possono attendere un momento o due in più mentre viene generato un thread per gestire la loro richiesta.
Tuttavia lo spawn di un processo non è “immediata” e pertanto se cerchi di ottenere le massime performance e guadagnare anche pochi millisecondi la modalità ondemand è sicuramente la meno performante tra le tre disponibili.
Sito ad alto traffico
Se hai un sito Web ad alto traffico, è consigliabile utilizzare la modalità static
e regolare le impostazioni in base alle tue esigenze nel tempo e alle risorse hardware disponibili. Potrebbe sembrare eccessivo avere un gran numero di processi figlio sempre pronti a ricevere richieste, ma per siti ad alto traffico è fondamentale che le risposte siano rapide e immediate.
I siti ad alto traffico devono rispondere il più rapidamente possibile. Pertanto, è essenziale utilizzare static
in modo che un numero sufficiente di processi figlio sia sempre pronto per gestire le richieste in arrivo. Questo approccio garantisce tempi di risposta rapidi, migliorando l’esperienza utente e riducendo il rischio di sovraccarico del server.
Utilizzando la modalità ondemand
, i processi figlio potrebbero consumare troppa memoria a causa della continua generazione e terminazione, e il ritardo di avvio dei processi potrebbe comportare una significativa riduzione delle prestazioni. Questo comportamento è generalmente inaccettabile per i siti ad alto traffico, dove ogni millisecondo conta.
La modalità dynamic
può rappresentare un compromesso, a seconda della configurazione specifica. In alcuni casi, potrebbe offrire prestazioni sufficienti, ma è possibile che si finisca con una configurazione che, di fatto, rispecchia la modalità static
. La scelta della modalità dipende dalle caratteristiche specifiche del sito e dalle risorse a disposizione, ma per ottimizzare le prestazioni dei siti ad alto traffico, static
rimane spesso la scelta migliore.
Utilizzo di più pool per frontend/backend
Ora un’ultima raccomandazione: servi il front-end e il back-end del tuo sito Web utilizzando diversi pool .
Supponiamo che tu abbia un sito di e-commerce, magari alimentato da Magento o WooCommerce Puoi considerare l’applicazione come composta da due parti:
- Un frontend in cui i clienti possono navigare ed effettuare acquisti
- Un back-end, in cui il personale amministrativo gestisce il negozio (ad esempio aggiungendo/rimuovendo prodotti , categorie e tag e rivedendo le valutazioni )
Se visto in questo modo, ha senso avere un pool che serve il front-end e un altro che serve il back-end e configurarli in modo appropriato.
Per quel che vale, puoi dividere qualsiasi applicazione in più parti usando questa strategia, se ha senso farlo. Ecco come farlo.
In /etc/php/7.2/fpm/pool.d/www.conf
, aggiungi la seguente configurazione:
; frontend [frontend] listen = /var/run/php-fpm-frontend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = static pm.max_children = 5
; backend [backend] listen = /var/run/php-fpm-backend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s
Questo crea due pool, uno per il front-end e uno per il back-end. Entrambi hanno lo stesso utente e gruppo, ma hanno diverse configurazioni del gestore di processo e sono collegati tramite socket diversi.
Il pool frontend utilizza una configurazione statica con un numero massimo ridotto di processi figlio. Il pool di backend utilizza la configurazione ondemand, anche con un numero ridotto di configurazioni. Questi numeri sono arbitrari, in quanto sono ai fini di un esempio.
Con quello salvato, per il tuo file vhost NGINX, potresti ad esempio usare la seguente configurazione:
server { listen 80; server_name test-site.localdomain; root /var/www/test-site/public;
access_log /var/log/nginx/test-site.access.log; error_log /var/log/nginx/test-site.error.log error; index index.php;
set $fpm_socket "unix:/var/run/php-fpm-frontend.sock";
if ($uri ~* "^/api/") { set $fpm_socket "unix:/var/run/php-fpm-backend.sock"; }
location / { try_files $uri $uri/ /index.php;
location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass $fpm_socket; fastcgi_index index.php; include fastcgi.conf; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } } }
In questo modo viene creata una configurazione dell’host virtuale che invia le richieste al pool front-end o back-end, in base alla posizione richiesta. Tutte le richieste /api
vengono inviate al pool di back-end e tutte le altre richieste vengono instradate al front-end.
Conclusioni
Questa è stata una rapida introduzione all’ottimizzazione di PHP-FPM per prestazioni migliori. Abbiamo esaminato le tre diverse configurazioni di process manager, le relative impostazioni e discusso quando ciascuna configurazione ha senso. Abbiamo quindi finito esaminando i workers pool.
Possiamo riassumere brevemente che quando si tratta di PHP-FPM, una volta che inizi a servire traffico intenso, i gestori di processi dinamici e ondemand per PHP-FPM possono limitare il throughput a causa del sovraccarico intrinseco. Conosci il tuo sistema e imposta i tuoi processi PHP-FPM in modo che corrispondano alla capacità massima del tuo server. Iniziare conpm.max_children
impostato in base all’utilizzo massimo di pm dynamic o ondemand e quindi aumentare al punto in cui la memoria e la CPU possono elaborare senza essere sovraccaricati. Noterai che con pm static, (poiché mantieni tutto in memoria) i picchi di traffico nel tempo causano meno picchi alla CPU e il carico del tuo server e le medie della CPU saranno più fluidi.
Aggiornamento: Abbiamo aggiunto grafico di confronto benchmark A/B. Avere processi PHP-FPM in memoria aiuta le prestazioni al prezzo di un maggiore utilizzo della memoria per tenerli in attesa.
Nel caso in cui stiate cercando un tuning ad hoc e minuzioso dell’interprete PHP, possiamo offrire questo servizio personalizzato per ottimizzare al meglio le prestazioni del vostro sito. Contattateci per una consulenza dettagliata e scoprite come possiamo aiutarvi a migliorare significativamente la velocità e l’efficienza del vostro ambiente PHP.