Aller au contenu principal
PHP-FPM

static, dynamic, ondemand : choisir le gestionnaire de processus PHP-FPM selon le trafic mesuré

Le mode de gestion des processus décide de la mémoire occupée au repos et de la latence sous charge. Il ne se choisit pas dans un tutoriel, mais dans la page d'état du pool, après quelques jours de trafic réel. Voici ce que chaque mode fait, ce qu'il coûte, et comment vérifier que le choix tient dans le temps.

Rangée de vélos de livraison identiques alignés dans une cour
static : tous les travailleurs sont là dès le démarrage, qu'une requête arrive ou non.

Le mode ne change qu'une chose : combien de travailleurs existent, et quand

La directive pm est obligatoire dans chaque pool et n'accepte que trois valeurs : static, dynamic et ondemand. Dans les trois cas, pm.max_children reste la limite du nombre de processus simultanés, donc du nombre de requêtes servies en parallèle. Le mode ne fixe pas ce plafond : il décide de la façon dont le pool s'en approche, et de ce qu'il laisse en mémoire quand personne ne demande rien.

La conséquence pratique tient en deux courbes. D'un côté la mémoire résidente, qui suit le nombre de processus présents. De l'autre la latence, qui augmente dès qu'une requête attend un travailleur libre. Un mode qui garde des processus au repos consomme de la mémoire sans servir personne ; un mode qui les crée à la demande économise cette mémoire, mais paie un délai au premier appel.

Hall désert avec un seul guichet éclairé au fond
ondemand : le travailleur ne se réveille qu'à la première requête, puis s'éteint après le délai d'inactivité.

static : un plancher de processus, utile quand la charge ne bouge pas

Avec static, php-fpm démarre exactement pm.max_children processus au lancement et n'en change plus. Chaque travailleur a déjà chargé PHP et l'application quand la requête arrive : la latence est la plus stable des trois modes, et il n'y a aucun coût de création en cours de journée. C'est le mode le plus simple à raisonner, parce qu'il n'a aucun paramètre à équilibrer.

Le prix est fixe lui aussi : la mémoire occupée est celle du plafond, y compris la nuit et les jours creux. Sur un serveur qui héberge aussi la base de données ou un autre pool, cette réservation permanente se paie en marge de sécurité. static se justifie quand le trafic mesuré reste proche du plafond pendant l'essentiel de la journée, ce qui est rare sur un site à pointe saisonnière.

dynamic : deux bornes, et un démarrage calculé

dynamic démarre pm.start_servers processus, puis maintient le nombre de travailleurs inactifs entre pm.min_spare_servers et pm.max_spare_servers, sans jamais dépasser pm.max_children. Les deux bornes de réserve sont obligatoires dans ce mode. pm.start_servers, lui, a une valeur par défaut calculée : la moyenne de min_spare_servers et de max_spare_servers.

C'est le mode qui s'adapte le mieux à un trafic irrégulier : assez de travailleurs chauds pour absorber la pointe, moins de processus la nuit. Deux réglages méritent l'attention. pm.max_spawn_rate, fixé à 32 par défaut, limite le nombre de processus créés d'un coup : une montée en charge très brutale est donc servie par vagues. Et un min_spare_servers trop bas provoque des créations répétées au moindre pic, ce que la page d'état montre sous forme d'un total de processus qui oscille.

Parking à vélos vu de haut, quelques vélos garés et des emplacements libres
dynamic : le nombre de travailleurs oscille entre min_spare_servers et max_spare_servers selon la demande.

ondemand : aucun processus au repos, un délai à la première requête

ondemand ne démarre rien au lancement : un travailleur est créé quand une requête arrive, puis tué après pm.process_idle_timeout, fixé à 10 secondes par défaut. pm.start_servers et les deux bornes de réserve ne sont pas utilisés dans ce mode. Sur un site qui reçoit quelques visites par heure, c'est la configuration la moins gourmande en mémoire, et de loin.

Le revers est un délai de démarrage à chaque réveil du pool, qu'il faut mesurer plutôt que supposer : il dépend du temps de chargement de l'application, de la taille du code et de l'état de l'OPcache. Sur un trafic soutenu, le va-et-vient des processus annule l'économie et ajoute de la latence. ondemand convient donc à un pool de faible trafic ou à un site secondaire posé sur une machine déjà chargée, pas à un site qui reçoit des visiteurs en continu.

Mesurer avant de trancher : la page d'état et la mémoire réelle

pm.status_path expose une page d'état qui donne le mode en cours, les processus inactifs et actifs, le total, le nombre maximal de travailleurs atteint et la file d'attente. Un indicateur de plafond atteint resté à zéro après plusieurs jours signifie que pm.max_children n'a jamais été touché ; une file qui monte au contraire indique une saturation, même si les moyennes horaires paraissent calmes.

La mémoire se lit à part, processus par processus : le fichier /proc/PID/status donne VmRSS, la mémoire résidente, et ps permet de vérifier que tous les travailleurs d'un pool partagent bien le même utilisateur et le même parent. Multiplier un VmRSS observé par le nombre de travailleurs visés donne un ordre de grandeur à confronter à la mémoire disponible, marge système comprise.

  • process manager : static, dynamic ou ondemand, le mode réellement appliqué.
  • idle processes et active processes : les travailleurs libres et occupés à l'instant du relevé.
  • max children reached : le plafond a-t-il déjà été atteint depuis le démarrage.
  • listen queue et max listen queue : la file d'attente, révélatrice d'une saturation.

Ce qui casse le plus souvent quand on change de mode

Les erreurs de réglage se ressemblent : des bornes incohérentes, un min_spare_servers supérieur à max_spare_servers ou un start_servers hors de l'intervalle, empêchent le pool de démarrer ; un pm.max_children trop haut pour la mémoire disponible provoque des processus tués par le noyau, visibles dans le journal système, et des 502 en série. Dans dynamic, un plafond atteint sans marge se traduit par une file qui grandit avant que le serveur web ne cesse de répondre.

La méthode raisonnable tient en trois temps : relever une journée complète dans le mode actuel, changer un seul paramètre à la fois, puis relire la page d'état et la mémoire après la recharge du service. Garder une copie du fichier de pool avant modification permet de revenir en une commande si la latence se dégrade. Un mode n'est pas meilleur en soi : il est adapté à un profil de trafic, et ce profil se mesure.