Les requêtes HTTP peuvent se bloquer même si le CPU, la RAM et la bande passante semblent ouverts, car des limites invisibles, des filtres et des files d'attente interviennent tout au long de la chaîne. J'explique où Frontières et quels sont les paramètres que je définis pour que les demandes soient à nouveau fluides.
Points centraux
Avant d'entrer dans les détails, je résume les principales causes et indique ce que je regarde en premier. Ces points couvrent les goulots d'étranglement typiques qui conduisent à un embouteillage malgré les ressources disponibles. Je garde volontairement la liste compacte afin que vous puissiez examiner immédiatement les points de départ. Ce qui est décisif, c'est que chaque couche a ses propres règles qui s'appliquent indépendamment du CPU et de la RAM. Celui qui connaît ces règles résout rapidement de nombreux temps d'attente „inexplicables“.
- Limites de travailleurs: Trop peu de processus/threads bloquent les nouvelles connexions malgré une CPU libre.
- Couche de sécurité: les WAF/filtres web bloquent des modèles, des méthodes ou des clients, souvent sans charge élevée.
- Concurrence: PHP-FPM, la base de données et les proxies limitent les sessions simultanées.
- Keep-Alive/TimeoutsLes longues connexions mobilisent des slots, les requêtes atterrissent dans des files d'attente.
- Filtre client: les extensions de navigateur arrêtent les requêtes avant qu'elles n'atteignent le serveur.
Ces points de repère suffisent souvent pour examiner le comportement de manière ciblée. Je montre ci-après comment j'en déduis des mesures concrètes et Blocages délimiter proprement.
Pourquoi les requêtes HTTP se bloquent-elles malgré des ressources libres ?
Une requête passe par plusieurs couches : Client, réseau, filtre, serveur web, environnement d'exécution et base de données. Chaque couche apporte ses propres Limites qui s'appliquent indépendamment du CPU, de la RAM ou de la bande passante. Si des slots de travail sont occupés ou si des règles sont actives, la demande attend dans une file d'attente ou est immédiatement éliminée. Ce temps d'attente n'apparaît souvent pas dans les diagrammes de ressources classiques. C'est précisément ce qui conduit à l'idée erronée que le serveur est „vide“, alors que les demandes ne sont pas traitées.
Couche de sécurité : WAF, filtres et règles du fournisseur d'accès
De nombreux blocages surviennent avant même que l'application ne fonctionne. Les pare-feu d'applications web, les IDS/IPS et les filtres côté fournisseur détectent des modèles et les ralentissent ou les bloquent [1][5][9]. Il suffit alors de paramètres suspects, d'anciens protocoles ou de combinaisons de méthodes pour Verrouillage d'allumer le feu. Du point de vue de l'opérateur, cela ressemble à une erreur de serveur, mais la décision est prise „en amont“. Je vérifie donc les protocoles du WAF et note l'ID de la requête, l'IP, l'heure et le code d'état. Ces données permettent d'identifier la règle et de l'adapter de manière ciblée, sans pour autant jeter la sécurité par-dessus bord.
Côté client : extensions de navigateur et bloqueurs locaux
Toutes les demandes n'atteignent pas le serveur. Les adblockers, les gestionnaires de mots de passe et les bloqueurs de scripts arrêtent déjà les URL dans le navigateur ; les DevTools indiquent alors „Requests to the Server Have Been Blocked by an Extension“ [3][7]. Je teste dans une fenêtre privée, je désactive les extensions et je vérifie si le Demande a même été envoyée. De plus, il est utile de contrôler les priorités dans le front-end, par exemple avec un Priorisation des demandes pour les actifs critiques. J'évite ainsi que des appels de tiers non critiques ne retardent des itinéraires importants.
Comprendre la méthode et le routage : 405, 403, 429
Un 405 „Method Not Allowed“ indique clairement que le serveur connaît la ressource, mais n'autorise pas la méthode utilisée [5]. De même, 403 indique des filtres ou des droits et 429 une limitation de taux active. Dans les logs, je peux rapidement voir si une règle globale a été appliquée à des méthodes telles que PUT ou DELETE ou si un point de terminaison n'a jamais été implémenté. J'adapte alors le routage, le contrôleur ou la règle WAF. Ainsi, le prétendu „blocage“ se résout en une correction propre des méthodes et des chemins.
Architecture du serveur web et limites des travailleurs
Apache, NGINX, LiteSpeed et OpenLiteSpeed gèrent les connexions différemment [4]. Le nombre de processus de travail, de threads et la manière dont les sockets Keep-Alive occupent les slots sont décisifs. Si tous les workers sont occupés par de longues connexions, les nouvelles requêtes se déplacent dans un Queue, bien que le CPU et la RAM semblent libres. C'est pourquoi j'évalue les états de connexion et j'adapte les travailleurs, le backlog et les temps de maintien en ligne. Des connaissances de base sur les files d'attente aident, par exemple sur le thème Mise en file d'attente du serveur et la latence.
| couche | Limite pertinente | Symptôme typique | Indication de diagnostic |
|---|---|---|---|
| Serveur web | Nombre de worker/thread | files d'attente, 503 en charge | Modules d'état, vérifier les états de connexion |
| PHP-FPM/FastCGI | max_enfants / pm | Requêtes pendantes, temps de réponse élevé (time-to-first byte) | FPM logs, slow log, nombre de processus |
| Base de données | max_connections | Erreur „Too many connections“ (trop de connexions)“ | SHOW PROCESSLIST, pics de connexion |
| WAF/Filtre | Signatures, méthodes | 403/405, posts de formulaires cassés | Logs WAF, ID de hits de règles |
| Équilibreur de charge | Limite de connexion per-backend | Temps de réponse inégaux | LB-Stats, Backend-Health |
Concurrence dans PHP-FPM, base de données et proxies
Souvent, le traitement simultané éclate d'abord dans l'environnement d'exécution. Si tous les workers PHP-FPM sont occupés, il n'y a pas de créneau disponible pour de nouveaux scripts ; les requêtes attendent, bien que les CPU ne fonctionne pratiquement pas. Il en va de même pour les bases de données avec max_connections ou pour les proxies avec des limites de connexion par backend. J'optimise d'abord la durée des différentes requêtes avant d'augmenter les limites. Je réduis ainsi le temps d'occupation par créneau et diminue la probabilité que les files d'attente s'allongent.
Backends lents et verrouillage de session PHP
Les longues requêtes de base de données, les API externes ou les E/S de fichiers retiennent nettement plus longtemps les travailleurs. De plus, le verrouillage de session peut ralentir des chaînes entières, par exemple pour les identifiants WordPress ou les paniers d'achat. Je vérifie si les demandes parallèles adressées au même identifiant de session se succèdent au lieu de s'exécuter simultanément. Si c'est le cas, j'opte pour un déverrouillage ciblé, je réduis les accès critiques en écriture et je suis les conseils éprouvés en matière de Verrouillage de session PHP. Cela me permet de libérer les créneaux plus rapidement et de réduire les coûts. Temps d'attente perceptible.
Timeouts, Keep-Alive et stratégies de connexion
Des temps de keep alive trop longs mobilisent des ressources, des temps trop courts génèrent des handshakes et de la latence. Je choisis des valeurs adaptées au profil de trafic et fixe des limites pour les timeouts de l'en-tête, du corps et du backend. Il est important de ne pas limiter les délais d'attente au Serveur web mais de manière uniforme tout au long de la chaîne : proxy, app, base de données. En outre, j'évite le blocage à l'inactivité grâce à des réglages HTTP/2/HTTP/3 plus précis et à une priorisation. Ainsi, les slots restent disponibles sans que les clients ne doivent constamment se reconnecter.
Modèles d'hébergement : partagé, VPS, dédié
L'hébergement mutualisé applique des filtres précoces et des quotas stricts pour que la plateforme reste équitable [1]. Sur VPS, les fournisseurs isolent le CPU et la RAM, mais conservent des limites pour les E/S, le réseau ou la sécurité ; les différences de performance et de surveillance sont évidentes [10]. Sur les serveurs dédiés, j'assume l'entière responsabilité du serveur web, de la base de données et de la configuration WAF. Des comparaisons montrent que les piles modernes avec HTTP/3, NVMe et protection DDoS présentent des avantages évidents [2][6][11][8]. Ceux qui ont besoin d'un parallélisme élevé profitent de systèmes clairement documentés. Frontières et un support qui aide à résoudre les problèmes de règles.
Analyse systématique : étape par étape
Je commence par la source : DevTools envoie-t-il vraiment la requête ou une extension bloque-t-elle [3][7] ? Ensuite, je regarde les codes d'état : 403/405/429/503 donnent de fortes indications sur les filtres, les méthodes ou la capacité [5]. En parallèle, je vérifie les logs du serveur web, de l'app et du WAF pour trouver des modèles et des signatures récurrentes [1][9]. Ensuite, je contrôle le nombre de travailleurs, les paramètres FPM, les connexions Keep-Alive et de base de données et j'augmente les limites à titre de test avec des points de mesure avant et après. Pour finir, je simule la charge, j'observe les goulots d'étranglement en temps réel et je vérifie que les Files d'attente rétrécissent.
Meilleures pratiques contre les blocages
Je formule des objectifs de concordance par couche et fixe des limites de manière à amortir les pics de charge. Le serveur web doit être adapté au modèle de trafic ; des benchmarks aident au choix et à la configuration [4]. J'optimise d'abord les backends de manière logique : des requêtes plus rapides, des transactions plus courtes, moins de sections en série. Je maintiens des règles de sécurité suffisamment strictes contre les attaques, mais avec des exceptions pour les sites légitimes. Échantillon. La surveillance ne s'arrête pas au CPU/RAM : je regarde les connexions, les files d'attente, les temps de réponse et les codes d'erreur pour que les goulots d'étranglement restent visibles [6][11].
Notes pratiques : demande de blocage de l'hébergement
Dans les environnements partagés, les blocages arrivent souvent avant l'espace web proprement dit ; le support a alors besoin de données de requête concrètes pour ajuster les règles [1]. Sur VPS, j'évolue progressivement : plus de travailleurs, des valeurs de maintien en ligne plus appropriées et une surveillance plus étroite de la base de données [10]. Sur mon propre matériel, je décide de l'équilibrage de charge, des règles WAF et des limites par backend. Les projets avec des accès fortement parallèles profitent d'une configuration HTTP/2/HTTP/3 propre et de réserves claires pour Pointes. Si l'on s'attend à une croissance, il faut prévoir suffisamment tôt le passage à des tarifs plus performants, ce qui permet d'économiser par la suite beaucoup de travail de tuning [2][6][10][11].
Limites du réseau et du noyau : backlog, ports et descripteurs
Outre le serveur web et l'application, le noyau limite le nombre de connexions qui arrivent, sont établies et sont gérées simultanément. Je vérifie d'abord le Liste-BacklogMême si le serveur web a beaucoup de travailleurs, la file d'attente d'acceptation peut être serrée. L'interaction entre l'application (listen backlog), le noyau (somaxconn) et le backlog SYN (tcp_max_syn_backlog) détermine si les connexions restent dans la file d'attente ou sont rejetées. Les symptômes sont des temps de connexion croissants et des retransmissions - avec une faible utilisation du CPU. Je compare les valeurs et mesure l'utilisation réelle des files d'attente afin d'éviter les drops.
Un autre classique est la Tableau conntrack dans les configurations NAT/pare-feu. Lorsqu'elle est pleine, les connexions disparaissent „sans laisser de trace“ ; l'application ne voit jamais de requête. Je le constate par des messages dans le journal système et par des délais d'attente brusques lors des pics de charge. Les contre-mesures sont les suivantes : taille appropriée de la table, délais d'attente réalistes pour les protocoles, moins de chemins NAT inutiles et des alias de sauvegarde efficaces qui réutilisent les connexions de manière judicieuse.
Je vérifie aussi le nombre de dossiers Descripteurs de fichiers (ulimit -n). Si de nombreux sockets et fichiers simultanés rencontrent des limites restrictives, Accept échoue („too many open files“) et les nouvelles demandes s'accumulent devant. Le remède est généralement banal : ramener les limites nofile pour le serveur web, le proxy et la base de données à un niveau sain - et ce de manière persistante, pas seulement interactive.
Dans les configurations fortement parallèles, j'observe les Plage de ports éphémères et TIME_WAIT-état de la connexion. Derrière les passerelles NAT, les ports sources disponibles s'épuisent lorsque des connexions courtes sont établies en masse. Je mise donc sur la réutilisation des connexions (Keep-Alive, HTTP/2/3), je réduis la brièveté inutile et je règle prudemment la gestion TIME_WAIT sans risquer la stabilité. Résultat : moins d'expiration de port et des temps de connexion plus stables sous charge.
Sur la carte réseau, je vérifie les longueurs de file d'attente, les paramètres de déchargement et la répartition des IRQ. Des interruptions mal réparties ou des files d'attente surchargées génèrent des pics de latence qui passent inaperçus dans les logs d'application. Avec un IRQ-Balancing équilibré et des paramètres Qdisc judicieux (mot-clé Bufferbloat), je réduis la latence sans limiter la bande passante.
HTTP/2 et HTTP/3 : utiliser correctement le multiplexage
Le multiplexage résout de nombreux problèmes, mais apporte de nouvelles limites : Nombre maximal de flux, Les fenêtres de contrôle de flux et les délais d'attente s'appliquent à chaque connexion. Si la valeur des flux simultanés est trop basse, les nouvelles demandes „se bloquent“ bien que la connexion TCP ou QUIC soit établie. Je vérifie donc combien de ressources critiques doivent être chargées en parallèle et j'adapte prudemment les limites de flux. En même temps, je veille à ce que les flux soient raisonnables Flow-Control-fenêtre pour que les réponses de grande taille ne soient pas étranglées.
Le multiplexeur HTTP/2 sur TCP peut souffrir d'un blocage en tête de ligne en cas de perte de paquets ; HTTP/3 sur QUIC contourne ce problème, mais exige des paramètres TLS/ALPN propres et des règles de gestion de chemin stables. Je teste les deux chemins et sélectionne de manière ciblée les protocoles qui correspondent au profil de trafic. Important : ne pas faire aveuglément confiance à la priorisation - les navigateurs et les serveurs l'interprètent différemment. Je me concentre sur les itinéraires critiques et vérifie si les priorités sont réellement efficaces et si les slots ne sont pas occupés par des flux secondaires de longue durée.
CORS, preflights et limites d'en-tête/de corps
Toutes les erreurs 4xx ne proviennent pas du serveur. Infractions CORS se produisent dans le navigateur et apparaissent dans la console, pas dans le journal d'accès. Je vérifie si les requêtes de contrôle en amont (OPTIONS) sont correctement traitées et si les WAF/proxies autorisent cette méthode. S'il manque des en-têtes tels que Access-Control-Allow-Methods/-Headers, le navigateur „bloque“ la réponse - sans aucune charge pour le serveur.
Un autre goulot d'étranglement : Tailles des en-têtes et des cookies. Les cookies surabondants, les nombreux en-têtes Vary ou les grandes lignes de référents conduisent à des erreurs 431 ou à des drops silencieux à travers les limites de la mémoire tampon. Je limite le poids des cookies, je consolide les en-têtes et je définis des tailles de tampon cohérentes le long de la chaîne. Pour les téléchargements, je fais attention aux limites de corps, à la gestion des 100 continues et à la cohérence de l'ensemble. Chunked-Encoding-Support de tous les proxies. Si les limites de body et d'upload ne correspondent pas, les clients attendent une libération qui n'arrive jamais - les requêtes semblent rester „bloquées“.
DNS et TLS : les handshake comme latence cachée
La résolution DNS et la négociation TLS sont des points aveugles fréquents. Les chaînes CNAME multiples, les résolveurs lents ou les mésappariements IPv6/IPv4 prolongent le temps de démarrage sans solliciter l'unité centrale. Je réduis les sauts DNS inutiles, je définis des TTL judicieux et je veille à ce que les chemins des résolveurs soient rapides. Côté TLS, je vérifie les chaînes de certificats, les suites de chiffrement activées, l'étalement OCSP et la résomption de session. Un handshake ALPN propre empêche les downgrades vers HTTP/1.1, qui sollicitent davantage les slots Keep-Alive. Résultat : un time-to-first-byte plus court et un parallélisme plus stable, notamment sur les réseaux mobiles.
CDN/Edge : mise en cache, limites de débit et réputation IP
Entre le client et Origin, les CDN, les proxies inversés et les systèmes de protection contre les DDoS déterminent Passage et de l'étranglement. Je vérifie si les routes critiques sont correctement mises en cache (stale-while-revalidate, stale-if-error) et si les caches négatifs retiennent les erreurs plus longtemps que nécessaire. Les limites de taux, la gestion des bots et la réputation des IP peuvent atténuer le trafic légitime, en particulier dans le cas de réseaux partagés ou d'un accès API important. Je segmente le trafic (par ex. API vs. Assets), définis des clés de cache claires et désamorce les règles de manière sélective pour les clients dignes de confiance. Je décharge ainsi Origin et évite que les files d'attente CDN ne se développent alors que le serveur semble „sous-utilisé“.
Conteneurs et orchestration : cgroups, Ingress et conntrack
Dans les conteneurs, les règles suivantes s'appliquent Limites de cgroup pour le CPU, la RAM, les pids et les fichiers. Un quota CPU trop serré entraîne un throttling : les processus attendent du temps CPU alors que l'hôte est libre. Je contrôle les quotas et m'assure que les pods ingress/proxy ont suffisamment de descripteurs de fichiers et de tampons. Dans Kubernetes, je contrôle les timeouts d'Ingress, les sondes de lecture/viabilité et les implémentations de services (IPVS), car les sondes ou timeouts défectueux génèrent une latence en zigzag et des redémarrages inutiles.
Un goulot d'étranglement souvent négligé Capacité NAT/conntrack par nœud. De nombreuses connexions éphémères (par ex. egress vers des API externes) remplissent le tableau conntrack, puis les requêtes „disparaissent“ dans le réseau. Je redimensionne le tableau, fixe des délais d'attente réalistes et regroupe les appels externes afin de réduire le nombre de nouvelles connexions. Je planifie les PodDisruptionBudgets, les Rolling Updates et la mise à l'échelle des HPA de manière à ce qu'aucune capacité ne soit prélevée sur l'ordonnanceur aux heures de pointe - sinon, des files d'attente se forment, même si l'app théorique aurait assez de travailleurs.
Observabilité : corrélation, traçage et métriques pertinentes
Pour trouver rapidement les blocages, j'ai besoin corrélation continue. J'attribue des identifiants de requête (par exemple traceparent) à Edge, au serveur web, à l'application et à la base de données et je les écris dans les logs. Je peux ainsi voir si une requête échoue au niveau du WAF, attend au niveau du serveur web, est suspendue dans la file d'attente FPM ou bloquée dans la base de données. Je travaille avec Histogrammes plutôt que de simples moyennes, et j'observe la latence P95/P99, les connexions ouvertes, la file d'attente d'acceptation, la longueur de la file d'attente FPM, les sessions DB actives et les codes d'erreur du backend. En complément, j'utilise des contrôles synthétiques pour séparer clairement les effets du côté client de ceux du côté serveur.
En cas d'anomalie, j'utilise un Drilldown-Procédure : d'abord les logs Edge/WAF, puis Load-Balancer, puis Webserver Access/Error, puis les logs App et FPM et enfin les logs DB et System. Ce chemin me montre exactement où le temps est perdu et à quelle limite la requête s'arrête. Grâce à des métriques ciblées par couche, j'évite l'instinct et je réduis drastiquement le temps nécessaire pour trouver la cause.
Playbook de tuning et liste de contrôle
Pour la pratique, je tiens à disposition un Playbook compact que j'adapte à l'environnement :
- Reproductibilité: épingler le scénario (route, méthode, taille, client), consigner l'horodatage et les identifiants.
- Contrôler par couche: Browser/Extensions, CORS/Preflight, WAF-Hits, LB-Stats, Webserver-Status, FPM-Queue, DB-Active/Locks.
- Rendre les files d'attente visibles: Backlog d'acceptation/SYN, file d'attente d'écoute FPM, backlog de proxy, pool de connexion DB.
- Ajuster les limites: Worker/Threads, somaxconn, nofile, max_connections, limites de flux pour H2/H3, limites de corps/d'en-tête, timeouts.
- Réduire le temps d'occupation: Accélérer les requêtes, éviter les blocages de session, réduire les E/S, comprimer les réponses et les mettre en cache de manière judicieuse.
- Harmoniser les stratégies: durée du keep-live, paramétrage HTTP/2-/3, priorisation des routes critiques.
- Ajuster la sécurité: exclure les règles WAF de manière ciblée au lieu de les affaiblir globalement ; journalisation avec Hit-IDs.
- Mise à l'échelleDéfinir la concordance par équipe, effectuer des tests de charge, mesurer les réserves, n'augmenter les limites qu'après optimisation.
- Fallbacks: coupe-circuit pour les backends lents, politique de retry avec gigue, „stale-if-error“ pour les actifs critiques.
En bref
Les demandes bloquées lorsque le CPU et la RAM sont libres sont généralement dues à des limites, des filtres et des stratégies de connexion - et non à un manque de performance. Je vérifie d'abord où la demande s'arrête : navigateur, WAF, serveur web, temps d'exécution ou base de données. Ensuite, je minimise les temps d'occupation par slot, j'élimine les requêtes inutiles et j'utilise les ressources disponibles. Locks et je fixe des délais d'attente réalistes. Je maintiens la sécurité à un niveau élevé, j'ajuste les règles contre les fausses alertes et je rassemble les preuves dans les logs. Grâce à cette approche, les requêtes HTTP restent accessibles de manière fiable, même lorsque le trafic augmente brusquement et que chaque seconde compte.


