Préparer une application PHP aux pics de trafic ne consiste pas à multiplier le nombre habituel de visites par un facteur arbitraire. La capacité nécessaire dépend du nombre de requêtes simultanées, de leur durée et du travail qu’elles exécutent : une page mise en cache et une opération qui interroge plusieurs services externes ne consomment pas les mêmes ressources.
L’objectif opérationnel est de savoir quel composant limite le service sous une charge représentative, quelle marge reste disponible et que faire lorsque cette marge est épuisée. Les tests fournissent des éléments probants pour prendre des décisions ; ils ne garantissent pas une capacité universelle, car le résultat dépend du code, de l’infrastructure, des données et du profil d’utilisation réel.
Estimer la charge selon la concurrence et le type d’opération

Le volume quotidien ou mensuel ne suffit pas pour dimensionner. Une application peut recevoir de nombreuses visites réparties sur plusieurs heures et fonctionner avec une large marge, ou concentrer les requêtes sur quelques minutes et saturer. Pour estimer la pression, observez le taux d’arrivée, la durée des requêtes et la proportion d’opérations concurrentes.
À titre indicatif, si la durée augmente alors que le taux d’arrivée reste stable, davantage de requêtes restent actives en même temps. Une dépendance lente peut donc accroître la concurrence même si le trafic entrant ne change pas. Le trafic peut aussi être inégal : une campagne peut provoquer une forte hausse des pages produit et des recherches, tandis qu’une fin de période concentre les authentifications, les exports ou les écritures.
Commencez par identifier les routes et les opérations qui influent sur les objectifs métier. Incluez, par exemple, la navigation publique, la recherche, la connexion, la création de commandes et les tâches administratives importantes. Distinguez les lectures des écritures, les requêtes pouvant être mises en cache de celles qui ne le peuvent pas, ainsi que les requêtes synchrones des tâches qui pourraient être traitées dans une file d’attente. N’utilisez pas la moyenne globale pour masquer une route lente ou critique.
Construire un test représentatif et sûr
Définissez un ou plusieurs scénarios à partir de la télémétrie disponible, des journaux d’accès et du calendrier des événements connus. Documentez la proportion de requêtes correspondant à chaque opération, l’évolution du taux d’arrivée et la durée de chaque phase. Il est utile de tester une charge soutenue et une augmentation rapide, car elles révèlent des comportements différents : l’épuisement progressif des ressources, d’une part, et une réaction brutale face à un pic, d’autre part.
Le test doit être exécuté dans un environnement dont la configuration représente suffisamment celle de la production pour que les résultats soient utiles. Examinez les écarts concernant le nombre de processus, les limites de connexion, les caches, le volume de données et les dépendances. Si un test est exécuté sur une machine isolée avec de petites tables, il ne démontre pas comment la production réagira. Évitez de générer de la charge sur des utilisateurs réels sans plan ni autorisation explicites.
Protégez les données dès la conception du scénario. Utilisez des données synthétiques ou anonymisées, des identifiants dédiés et des autorisations minimales ; ne copiez pas de données personnelles dans des outils de test de charge sans base appropriée ni contrôles adaptés. Évitez que les tests envoient des e-mails, débitent des paiements ou produisent des effets irréversibles. Pour les opérations externes, utilisez des environnements de test ou des substituts contrôlés, en gardant à l’esprit qu’un substitut ne reproduit pas nécessairement la latence ni les limites du service réel.
Mesurer simultanément la latence, les erreurs et la saturation
Enregistrez la latence par route et observez des percentiles tels que p50, p95 et p99. La moyenne peut rester stable alors qu’une partie des requêtes devient très lente ; les percentiles rendent mieux compte de cette longue traîne. Mesurez également le taux d’erreur, les délais d’attente et le nombre de requêtes traitées par unité de temps. Un test qui génère de nombreuses requêtes mais aussi de nombreuses erreurs ne démontre pas une capacité utile.
Mettez ces mesures en relation avec les ressources et les files d’attente. Avec PHP, observez l’occupation et la file d’attente des processus qui traitent les requêtes, ainsi que le CPU, la mémoire et les redémarrages. Si vous utilisez PHP-FPM, examinez la configuration et les métriques de ses processus et du serveur web ; le nom de l’indicateur disponible dépend de l’instrumentation. Dans la base de données, mesurez les connexions actives, le délai d’attente pour obtenir une connexion, les requêtes lentes, les verrous et l’utilisation du CPU ou du disque. Surveillez également les caches, les files d’attente et les dépendances externes.
Définissez des seuils liés à l’expérience et aux opérations, et pas uniquement à l’utilisation du CPU. Par exemple, une route d’achat peut nécessiter une latence et un taux d’erreur maximaux convenus, tandis qu’un export non critique peut tolérer une attente ou un traitement asynchrone. Vérifiez que les horloges et les fenêtres d’observation sont comparables et que vous pouvez associer une hausse de la latence au composant qui a saturé.
Repérer le premier goulot d’étranglement avant de passer à l’échelle
Recherchez le premier indicateur qui se dégrade lorsque la charge augmente progressivement. Si la file d’attente des processus web s’allonge et que le CPU de PHP reste élevé, il peut s’agir d’un travail coûteux par requête ou d’un nombre insuffisant de processus disponibles. Si les processus attendent des connexions alors que la base de données dispose encore de capacité, examinez la limite du pool ou la configuration des connexions. Si la base de données présente des requêtes lentes, des verrous ou une saturation, ajouter des processus PHP peut accroître la pression et aggraver le problème.
Les dépendances externes peuvent également mobiliser des processus. Examinez les temps de connexion et de réponse, les limites de débit et le comportement en cas d’erreur. Un délai d’attente trop long maintient les ressources occupées ; des tentatives répétées sans limite peuvent multiplier la charge. Définissez des délais d’attente plafonnés et une politique de nouvelles tentatives sélective, avec un délai progressif lorsque cela est approprié, et évitez de répéter automatiquement des opérations non idempotentes sans protection.
Distinguez le manque de capacité du manque d’efficacité. Une requête qui parcourt trop de lignes, des appels répétés au même service ou des calculs redondants resteront coûteux même si vous ajoutez des serveurs. Profilez des routes représentatives et réduisez le travail par requête : optimisez les requêtes et les index sur la base d’éléments probants, limitez les résultats, éliminez les appels inutiles et utilisez le cache lorsque la cohérence et la confidentialité le permettent. Répétez ensuite le test pour vérifier que l’amélioration se maintient sous charge.
Intervenir dans l’ordre et planifier des dégradations contrôlées
Commencez par réduire le coût du travail par requête et corrigez les requêtes ou les dépendances qui constituent un facteur limitant. Examinez ensuite les limites de concurrence, les processus web et les pools de connexions. Augmenter le nombre de processus peut améliorer le parallélisme jusqu’à la saturation du CPU, de la mémoire ou de la base de données ; configurer plus de connexions que la base de données ne peut en traiter ne fait que déplacer la file d’attente. Modifiez une variable à la fois et mesurez à nouveau.
La mise à l’échelle verticale — ajouter des ressources à une instance — peut être une intervention simple si le composant peut évoluer et qu’aucune limite structurelle n’est en jeu. La mise à l’échelle horizontale — ajouter des instances — exige que le déploiement, les sessions, les fichiers, les tâches et la base de données prennent en charge cette répartition. Vérifiez l’équilibrage de charge, le stockage partagé ou externe, le cas échéant, l’état de santé des instances et les limites communes, comme les connexions à la base de données. Aucune de ces options ne corrige à elle seule une requête inefficace.
Définissez ce qu’il faut préserver lorsque la capacité vient à manquer. Donnez la priorité à l’authentification, aux opérations essentielles ou aux confirmations de transaction, en fonction du produit ; différez les rapports, limitez les recherches coûteuses ou désactivez temporairement les fonctionnalités non indispensables. Utilisez des files d’attente pour les tâches qui peuvent être terminées ultérieurement et communiquez leur état à l’utilisateur. Appliquez explicitement des limites de débit ou des réponses de surcharge, avec des mécanismes de nouvelle tentative prudents. Une dégradation contrôlée doit éviter la perte d’opérations confirmées et proposer une solution de repli compréhensible, sans renvoyer un succès fictif.
Pour transformer les tests en décision opérationnelle, conservez un compte rendu du scénario, de la configuration, des résultats par route, de la première limite observée, des modifications apportées et du critère d’acceptation. Répétez le test après toute modification importante du code, de l’infrastructure, des données ou des dépendances. Avant un pic prévu, vérifiez les alertes, la capacité disponible, les procédures de retour arrière et les personnes responsables des décisions.
Liste de contrôle avant un pic

- Scénario : vérifiez qu’il reflète des routes, des proportions, un rythme et une durée plausibles, et qu’il inclut une hausse rapide et une charge soutenue.
- Sécurité : utilisez des données et des identifiants appropriés, évitez les effets réels indésirables et contrôlez la cible du test.
- Observabilité : mettez en corrélation la latence p95/p99, les erreurs et le débit avec les processus PHP, la base de données, le cache et les dépendances.
- Diagnostic : identifiez la première limite et confirmez si elle est due à la saturation, aux requêtes, à la concurrence ou aux attentes liées à des services externes.
- Modification : modifiez une cause à la fois, comparez les résultats et vérifiez que la saturation ne se déplace pas vers une autre couche.
- Résilience : définissez les limites, les priorités, les dégradations, la communication et le rétablissement sans perdre les opérations confirmées.
- Répétition : fixez des critères d’acceptation et recommencez les tests après des changements importants et avant les événements prévisibles.
Un dimensionnement rigoureux consiste à connaître le comportement de l’application dans des scénarios concrets et à prévoir une marge, plutôt qu’à viser un nombre abstrait d’utilisateurs. Les mesures montrent où investir : dans l’optimisation, l’ajustement de la concurrence, l’ajout de capacité ou une politique de dégradation qui maintient l’utilité des fonctions essentielles.



