PHP-FPM saturé : diagnostiquer un site lent

PHP-FPM saturé : comment diagnostiquer un site lent avant de changer d’hébergement

Résumer cet article via IA

Un site WordPress, PrestaShop ou développé en PHP peut devenir lent alors que le serveur ne semble pas manquer de puissance. Le processeur n’est pas constamment à 100 %, la mémoire paraît suffisante, mais les pages attendent plusieurs secondes avant de s’afficher. Dans certains cas, le site renvoie même des erreurs 502 ou 504.

Le problème peut venir de PHP-FPM. Plus précisément, le pool PHP peut être saturé : tous les processus disponibles traitent déjà une requête et les suivantes s’accumulent dans une file d’attente.

Ce diagnostic est différent d’un problème d’OPcache, de base de données ou de poids des images. Il se situe dans la manière dont le serveur lance et distribue les processus PHP. Voici une méthode pour vérifier cette piste sans modifier la configuration au hasard.

PHP-FPM, à quoi sert-il exactement ?

PHP-FPM, pour FastCGI Process Manager, est le composant qui exécute les scripts PHP lorsqu’un serveur web comme Nginx ou Apache lui transmet une requête.

Le fonctionnement peut être résumé ainsi :

  • le navigateur demande une page ;
  • le serveur web reçoit la requête ;
  • la requête dynamique est envoyée à PHP-FPM ;
  • un processus PHP exécute WordPress, PrestaShop ou le code de l’application ;
  • la réponse revient au serveur web, puis au navigateur.

PHP-FPM fonctionne avec un ou plusieurs pools. Chaque pool possède ses propres processus et ses propres réglages. C’est notamment dans cette configuration que l’on trouve pm.max_children, le nombre maximal de processus pouvant traiter des requêtes simultanément.

Un réglage trop bas limite inutilement la capacité du site. Un réglage trop haut peut consommer toute la mémoire disponible et provoquer du swap, des arrêts de processus ou une instabilité générale. Le bon nombre dépend donc de la mémoire réellement disponible et du poids moyen des processus PHP.

Reconnaître une saturation du pool PHP

Une saturation PHP-FPM ne se manifeste pas toujours de la même manière. Les symptômes dépendent du trafic, de la durée des requêtes et de la configuration du serveur.

Les indices les plus fréquents sont les suivants :

  • les pages dynamiques deviennent lentes alors que les fichiers statiques restent rapides ;
  • le back-office WordPress ou PrestaShop est plus lent que le site public ;
  • la lenteur apparaît surtout lors d’un pic de trafic ou d’une importation ;
  • les logs mentionnent parfois que le nombre maximal d’enfants a été atteint ;
  • des erreurs 502 ou 504 apparaissent de manière intermittente ;
  • le temps d’attente augmente alors que le temps d’exécution PHP lui-même n’explique pas tout.

Ces symptômes ne prouvent pas encore que PHP-FPM est la cause. Un appel externe lent, une requête SQL bloquée ou un module WordPress mal conçu peuvent monopoliser les processus et produire exactement le même effet. Il faut donc mesurer avant de changer un paramètre.

Commencer par distinguer attente et exécution

La première question à poser est simple : la requête attend-elle un processus PHP, ou bien un processus PHP travaille-t-il réellement pendant longtemps ?

Cette distinction est importante. Si les processus disponibles sont occupés par des requêtes longues, augmenter pm.max_children peut déplacer le problème sans le résoudre. Si les requêtes sont rapides mais que la file d’attente se remplit, le réglage du pool mérite davantage d’attention.

Pour comparer les situations, mesurez quelques pages représentatives :

  • une page statique, comme une image ou un fichier CSS ;
  • une page PHP très simple ;
  • la page d’accueil ;
  • une page lourde, comme une recherche, un panier ou une liste de produits ;
  • une page du back-office.

Répétez les tests à plusieurs moments. Un seul test réalisé depuis votre navigateur ne permet pas de distinguer une lenteur serveur d’un problème de réseau local ou de cache.

Vérifiez aussi les logs du serveur web et de PHP-FPM. Cherchez les erreurs 502, les délais d’expiration, les redémarrages du service et les messages indiquant que le maximum de processus a été atteint. Les noms et emplacements des fichiers varient selon la distribution, l’hébergeur et la version de PHP.

Utiliser la page de statut PHP-FPM

PHP-FPM peut exposer une page de statut dédiée avec la directive pm.status_path. La documentation PHP indique qu’elle peut fournir notamment le nombre de processus actifs et inactifs, la longueur actuelle de la file d’écoute, le maximum observé dans cette file, le nombre total de processus et le nombre de fois où la limite de processus a été atteinte.

Un exemple minimal de configuration de pool pourrait ressembler à ceci :

[www]
pm = dynamic
pm.max_children = 12
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.status_path = /fpm-status

Les valeurs ci-dessus sont uniquement illustratives. Elles ne constituent pas une recommandation à copier sur un site existant.

La page de statut doit être protégée. Elle révèle des informations sur les ressources et l’activité du pool. Elle ne devrait pas être accessible publiquement sans restriction. Selon le serveur web, on peut limiter l’accès à une adresse IP interne, à un réseau d’administration ou à une route non exposée sur Internet.

Les indicateurs à observer sont surtout :

  • active processes : les processus qui traitent actuellement une requête ;
  • idle processes : les processus disponibles ;
  • listen queue : les requêtes en attente d’un processus libre ;
  • max listen queue : le maximum de requêtes en attente depuis le démarrage ;
  • max children reached : indique si la limite de processus a déjà été atteinte ;
  • slow requests : le nombre de requêtes ayant dépassé le seuil de slowlog configuré.

Une file d’attente constamment nulle ne signifie pas que tout va bien, mais une file qui se remplit avec une limite max children reached active constitue un signal concret. Il faut ensuite comprendre pourquoi les processus restent occupés.

Activer un slowlog pour trouver les requêtes qui bloquent

PHP-FPM peut enregistrer une trace des requêtes qui dépassent un délai défini avec request_slowlog_timeout et slowlog. Le slowlog ne remplace pas un profiler applicatif, mais il aide à identifier le script et la pile d’appels qui restent actifs trop longtemps.

Exemple :

request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log

Un seuil de cinq secondes est un exemple de diagnostic. Il peut être trop élevé ou trop bas selon l’application. Sur un site e-commerce, une génération de rapport volontairement longue ne doit pas être confondue avec une requête normale qui se bloque.

Une fois le slowlog activé, reproduisez le problème dans un environnement contrôlé et observez :

  • le script concerné ;
  • la fonction ou le hook qui monopolise le processus ;
  • un appel HTTP externe qui ne répond pas ;
  • une requête SQL qui attend ;
  • un traitement d’import, d’export ou de génération de fichier ;
  • une boucle ou un traitement qui augmente avec le volume de données.

Sur WordPress, les extensions peuvent ajouter des traitements sur presque chaque requête. Avant de conclure à un problème d’infrastructure, il faut donc vérifier les plugins actifs, les appels AJAX, les tâches planifiées et les intégrations externes. L’article sur le choix des plugins WordPress rappelle notamment qu’une extension peut ralentir le site ou le back-office de différentes manières.

Ne pas confondre PHP-FPM et OPcache

OPcache et PHP-FPM travaillent ensemble, mais ils ne répondent pas au même problème.

OPcache conserve en mémoire le résultat de la compilation des scripts PHP. Il évite de refaire certaines étapes à chaque requête. PHP-FPM, lui, gère les processus qui exécutent ces requêtes.

Un OPcache mal configuré peut ralentir l’exécution ou servir un ancien code après un déploiement. Un pool PHP-FPM saturé peut faire attendre une requête avant même que le script commence son travail. Activer OPcache ne supprimera donc pas une file d’attente pleine, et augmenter le nombre de processus ne corrigera pas une requête qui reste bloquée sur une API externe.

Le diagnostic doit rester séparé :

  • mesurer l’exécution du code et l’état d’OPcache ;
  • mesurer le nombre de processus PHP-FPM et la file d’attente ;
  • mesurer la base de données et les appels externes ;
  • comparer ensuite les résultats.

Comment dimensionner pm.max_children sans deviner

pm.max_children ne doit pas être choisi en fonction d’un chiffre trouvé dans un article ou fourni automatiquement par un panneau d’hébergement.

Une méthode raisonnable consiste à :

  1. réserver la mémoire nécessaire au système, au serveur web, à la base de données et aux autres services ;
  2. mesurer la consommation moyenne et maximale d’un processus PHP ;
  3. définir une limite de mémoire réaliste pour le pool ;
  4. diviser cette mémoire disponible par la consommation observée d’un processus ;
  5. tester sous charge et surveiller le swap, les erreurs et la latence.

Cette estimation reste une base de travail. Deux requêtes PHP ne consomment pas nécessairement la même quantité de mémoire. WordPress avec un constructeur de pages, WooCommerce ou plusieurs extensions actives peut avoir un profil très différent d’un petit script PHP.

Si le serveur dispose de 2 Go de mémoire libre en théorie mais que la base de données et le système en utilisent déjà une grande partie, il serait dangereux de réserver le reste à PHP-FPM sans mesure. À l’inverse, un nombre trop faible de processus peut créer une file d’attente alors que la mémoire resterait disponible.

Le rôle de pm.max_requests

La directive pm.max_requests indique combien de requêtes un processus enfant peut traiter avant d’être relancé. PHP documente cette option comme un moyen de limiter l’impact de fuites mémoire dans des bibliothèques ou extensions tierces.

Elle ne corrige pas la fuite. Elle limite simplement la durée de vie du processus concerné. Un réglage comme 500 peut servir d’exemple de test, mais la valeur adaptée dépend du comportement observé et du coût des redémarrages.

Si la mémoire consommée par les processus augmente progressivement, vérifiez d’abord le code, les extensions PHP, les modules et les traitements longs. Utiliser pm.max_requests comme un pansement permanent sans chercher la cause peut masquer un problème important.

Avant de modifier la configuration en production

Une modification de PHP-FPM peut améliorer la latence, mais elle peut aussi épuiser la mémoire ou rendre le service instable. La procédure mérite donc quelques précautions :

  • notez la configuration actuelle ;
  • changez un seul paramètre à la fois ;
  • validez la syntaxe avant de recharger PHP-FPM ;
  • prévoyez un retour arrière ;
  • testez les pages publiques et le back-office ;
  • surveillez les logs, la mémoire, la file d’attente et les temps de réponse ;
  • vérifiez les tâches planifiées, les imports et les webhooks qui ne passent pas par un simple affichage de page.

Sur un hébergement mutualisé, vous n’aurez pas toujours accès au pool PHP-FPM. Dans ce cas, demandez au prestataire la valeur de pm.max_children, les indicateurs de saturation, les limites de processus et les traces disponibles. Une réponse utile doit s’appuyer sur des mesures, pas seulement sur l’affirmation que le serveur est “suffisant”.

Une méthode de diagnostic qui évite les fausses solutions

Face à un site lent, augmenter les ressources peut être nécessaire. Mais ce ne devrait pas être la première conclusion.

Commencez par établir quand la lenteur apparaît, quelles pages sont concernées et si le problème se situe avant ou pendant l’exécution PHP. Consultez ensuite les logs, la page de statut et le slowlog. Cherchez les requêtes longues, les appels externes, les requêtes SQL et les extensions qui occupent les processus.

Ce n’est qu’après cette étape qu’un ajustement de pm.max_children, de pm.max_requests ou du mode dynamic ou ondemand devient défendable.

Un serveur plus puissant peut repousser la saturation. Il ne rendra pas plus rapide un traitement qui attend indéfiniment une API, une base de données ou un service de cache mal configuré. Pour un site WordPress, PrestaShop ou une application PHP qui doit rester fiable dans le temps, la mesure et la traçabilité valent souvent mieux qu’un réglage appliqué au hasard.

Sources

Résumer cet article via IA
Thomas Pecriaux

Black Sheep Code

25 articles publishedExpertise: Wordpress, SEO, Prestashop, PHP Development