Table des matières de l'article :
PHP-FPM (ou Fast Process Manager) offre plusieurs avantages par rapport à mod_php , notamment une configuration plus flexible et le fait qu'il soit actuellement le mode d'exécution de PHP privilégié par une grande partie de la communauté. Cependant, si vous utilisez la configuration par défaut de votre gestionnaire de paquets, vous n'en tirerez probablement pas pleinement parti.
Dans cet article, je donnerai un bref aperçu de la manière d'améliorer les performances de PHP-FPM, en abordant les trois types de gestionnaires de processus PHP-FPM et en expliquant lequel est le plus adapté à chaque situation.
PHP-FPM peut utiliser l'un des trois types de gestion de processus suivants :
- statique (statique)
- dynamique (dynamique)
- à la demande (sur demande)
Voyons un peu en détail ce que chacun représente en allant identifier les avantages et les inconvénients des trois modes différents qui peuvent tout de même cohabiter tranquillement sur un même serveur.
Par exemple, nous pourrions avoir trois sites Web sur le même serveur, dont un fonctionnant en mode statique, un à la demande et un dynamique sans aucune restriction et avec une séparation totale des privilèges.
PHP en mode statique
Le mode statique garantit qu'un nombre fixe de processus enfants est toujours disponible pour traiter les requêtes utilisateur. Ce nombre est défini par ` pm.max_children` . Dans ce mode, les requêtes n'ont pas à attendre le démarrage de nouveaux processus, ce qui en fait l'approche la plus rapide.
En supposant que vous souhaitiez utiliser une configuration statique avec 10 processus enfants toujours disponibles, vous devez le configurer /etc/php/7.2/fpm/pool.d/www.conf(en supposant que vous utilisez le fichier de configuration PHP-FPM par défaut de Debian/Ubunut) comme suit :
pm = static pm.max_children = 10
Pour voir si le changement de configuration a été effectif, après avoir redémarré PHP-FPM, exécutez pstree -c -H <PHP-FPM process id> -S <PHP-FPM process id>. Cela montrera qu'il y a dix processus disponibles, comme dans l'exemple ci-dessous.
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 en mode dynamique
Dans ce mode, PHP-FPM gère dynamiquement le nombre de processus enfants disponibles et garantit qu'au moins un processus enfant est toujours disponible.
Cette configuration utilise cinq options de configuration ; ceux-ci sont:
pm.max_children: le nombre maximum de processus enfants pouvant être générés.pm.start_servers: le nombre de processus enfants à lancer au démarrage de PHP-FPM.pm.min_spare_servers: le nombre minimum de processus enfants inactifs que PHP-FPM créera. D'autres sont créés si moins que ce nombre sont disponibles.pm.max_spare_servers: Le nombre maximum de processus enfants inactifs que PHP-FPM créera. S'il existe plusieurs processus enfants de cette valeur, certains seront supprimés.pm.process_idle_timeout: le temps d'inactivité, en secondes, après lequel un processus enfant sera terminé.
Voici maintenant la partie intéressante : comment calculer les valeurs pour chaque réglage ? Sebastian Buckpesch propose la formule suivante :
| Réglage | Valeur |
|---|---|
| max_enfants | (RAM totale - Mémoire utilisée pour Linux, DB, etc.) / taille du processus |
| serveur_démarrage | Nombre de cœurs de processeur x 4 |
| min_spare_servers | Nombre de cœurs de processeur x 2 |
| max_spare_servers | Égal àstart_servers |
Nous devons également mettre en place pm.process_idle_timeout, qui est le nombre de secondes après lesquelles un processus inactif sera abandonné.
Disons que notre serveur a deux processeurs, chacun avec quatre cœurs et 8 Go de RAM. En supposant que Linux et ses démons utilisent environ 2 Go (utilisez free -hlpour obtenir une valeur plus précise), cela nous laisse environ 6192 Mo.
Maintenant, combien de mémoire chaque processus utilise-t-il ? Pour calculer cela, il existe un script Python appelé ps_mem.py . Après l'avoir exécuté, en utilisant sudo python ps_mem.py | grep php-fpm, vous obtiendrez une sortie semblable à celle-ci :
28.4 MiB + 33.8 MiB = 62.2 MiB php-fpm7.2 (11)
La première colonne est la mémoire privée. La deuxième colonne est la mémoire partagée. La troisième colonne est la RAM totale utilisée. La quatrième colonne est le nom du processus.
D'après ce qui précède, vous pouvez voir que la taille du processus est de 62,2 Mio. Ainsi, en mettant toutes ces informations dans notre formule, nous arrivons à ce qui suit :
# Round the result up. (8192 - 2000) / 62.2
Sur cette base, nous arrivons aux valeurs de réglage suivantes :
| Réglage | Valeur |
|---|---|
| max_enfants | 100 |
| serveur_démarrage | 32 |
| min_spare_servers | 16 |
| max_spare_servers | 32 |
Nous partirons pm.process_idle_timeoutle défaut de 10s. En supposant que nous soyons satisfaits de ces paramètres, nous le configurerions comme suit :
pm = dynamic pm.max_children = 100 pm.start_servers = 32 pm.min_spare_servers = 16 pm.max_spare_servers = 32 pm.max_requests = 200
Vous pouvez également utiliser régulièrement des outils de surveillance de la mémoire pour contrôler la quantité de mémoire utilisée par votre application. Plusieurs options sont disponibles pour PHP, notamment php-memprof.
PHP en mode à la demande
La méthode ondemand lance les processus fork PHP-FPM lorsque les requêtes sont reçues. Pour configurer PHP-FPM en mode à la demande, vous devez définir les paramètres suivants :
pm.max_childrenpm.process_idle_timeoutpm.max_requests
pm.max_requests définit le nombre de requêtes que chaque processus enfant doit exécuter avant de réapparaître. La documentation suggère que ce paramètre est utile pour contourner les fuites de mémoire.
En supposant que vous utilisiez les mêmes paramètres que dynamic, nous le configurerions comme suit :
pm = ondemand pm.max_children = 100 pm.process_idle_timeout = 10s pm.max_requests = 200
Quelle configuration vous convient ?
Honnêtement ? La réponse est « ça dépend », car cela dépend toujours du type d’applications que vous utilisez. Voici toutefois quelques conseils pour vous aider à choisir la configuration la plus adaptée.
Site à faible trafic
Si votre site génère peu de trafic, par exemple s'il héberge un panneau de contrôle comme cPanel , utilisez la gestion des requêtes à la demande. Cela permettra d'économiser de la mémoire, car les processus enfants ne seront lancés qu'en cas de besoin et arrêtés lorsqu'ils ne seront plus nécessaires. Comme il s'agit d'un serveur, les utilisateurs peuvent patienter quelques instants le temps qu'un thread soit créé pour traiter leur requête.
Cependant, l'apparition d'un processus n'est pas "immédiate" et donc si vous essayez d'obtenir des performances maximales et de gagner ne serait-ce que quelques millisecondes, le mode à la demande est certainement le moins performant des trois disponibles.
Site à fort trafic
Si vous avez un site internet à fort trafic, il est conseillé d'utiliser le mode static et ajustez les paramètres en fonction de vos besoins au fil du temps et des ressources matérielles disponibles. Il peut sembler écrasant d'avoir un grand nombre de processus enfants toujours prêts à recevoir des demandes, mais pour les sites à fort trafic, il est essentiel que les réponses soient rapides et immédiates.
Les sites à fort trafic doivent réagir le plus rapidement possible. Il est donc indispensable d’utiliser static afin qu'un nombre suffisant de processus enfants soient toujours prêts à gérer les demandes entrantes. Cette approche garantit des temps de réponse rapides, améliorant l'expérience utilisateur et réduisant le risque de surcharge du serveur.
Utiliser le mode ondemand, les processus enfants peuvent consommer trop de mémoire en raison de la génération et de l'arrêt continus, et le retard dans le démarrage des processus peut entraîner une dégradation significative des performances. Ce comportement est généralement inacceptable pour les sites à fort trafic, où chaque milliseconde compte.
Le mode dynamic peut représenter un compromis, en fonction de votre configuration spécifique. Dans certains cas, il peut offrir des performances suffisantes, mais vous pouvez vous retrouver avec une configuration qui, en fait, reflète le mode static. Le choix du mode dépend des caractéristiques spécifiques du site et des ressources disponibles, mais pour optimiser les performances des sites à fort trafic, static cela reste souvent le meilleur choix.
Utilisation de plusieurs pools par frontend / backend
Une dernière recommandation : utilisez des pools différents pour le front-end et le back-end de votre site web.
Supposons que vous ayez un site e-commerce, peut-être propulsé par Magento ou WooCommerce. Vous pouvez considérer l'application comme composée de deux parties :
- Une interface où les clients peuvent parcourir et effectuer des achats
- Un backend, où le personnel administratif gère le magasin (par exemple ajouter/supprimer des produits , catégories e Étiquette e revoir les notes )
Vu sous cet angle, il est logique d'avoir un pool servant le front-end et un autre servant le back-end et de les configurer de manière appropriée.
Pour ce que ça vaut, vous pouvez diviser n'importe quelle application en plusieurs parties en utilisant cette stratégie si cela a du sens. Voici comment procéder.
In /etc/php/7.2/fpm/pool.d/www.conf, ajoutez la configuration suivante :
; 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
Cela crée deux pools, un pour le front-end et un pour le back-end. Ils ont tous les deux le même utilisateur et le même groupe, mais ont des configurations de gestionnaire de processus différentes et sont connectés via des sockets différents.
Le pool frontal utilise une configuration statique avec un petit nombre maximal de processus enfants. Le pool principal utilise la configuration à la demande, même avec un petit nombre de configurations. Ces nombres sont arbitraires, car ils le sont à titre d'exemple.
Avec cela enregistré, pour votre fichier NGINX vhost, vous pouvez par exemple utiliser la configuration suivante :
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; } } }
Cela crée une configuration d'hôte virtuel qui envoie des demandes au pool frontal ou principal, en fonction de l'emplacement demandé. Toutes les demandes /apielles sont envoyées au pool principal et toutes les autres requêtes sont acheminées vers le serveur frontal.
Conclusions
Il s'agissait d'une introduction rapide à l'optimisation de PHP-FPM pour de meilleures performances. Nous avons examiné les trois configurations différentes du gestionnaire de processus, leurs paramètres et discuté du moment où chaque configuration a du sens. Nous avons ensuite fini par regarder les pools de travailleurs.
Nous pouvons brièvement résumer qu'en ce qui concerne PHP-FPM, une fois que vous commencez à traiter un trafic important, les gestionnaires de processus dynamiques et à la demande pour PHP-FPM peuvent limiter le débit en raison de la surcharge inhérente. Connaissez votre système et configurez vos processus PHP-FPM pour qu'ils correspondent à la capacité maximale de votre serveur. Commencer avecpm.max_childrendéfinissez l'utilisation maximale de pm dynamic ou ondemand, puis augmentez jusqu'au point où la mémoire et le processeur peuvent traiter sans être surchargés. Vous remarquerez qu'avec pm static (puisque vous gardez tout en mémoire), les pics de trafic au fil du temps entraînent moins de pics de CPU et la charge de votre serveur et les moyennes de CPU seront plus fluides.
Mise à jour : Nous avons ajouté un tableau comparatif des performances (A/B). Le maintien des processus PHP-FPM en mémoire améliore les performances, mais consomme davantage de mémoire.
Dans le cas où vous recherchez un réglage ponctuel et détaillé de l'interpréteur PHP, nous pouvons vous proposer ce service personnalisé pour optimiser au mieux les performances de votre site. Contactez-nous pour une consultation détaillée et découvrez comment nous pouvons vous aider à améliorer considérablement la vitesse et l’efficacité de votre environnement PHP.


