Avez-vous déjà évalué un serveur en laboratoire, puis l’avez-vous déployé pour un trafic réel, pour découvrir qu’il ne peut pas atteindre des performances proches des performances de référence ? L’utilisation du processeur est faible et il existe de nombreuses ressources gratuites, mais les clients se plaignent de temps de réponse lents et vous ne savez pas comment obtenir une meilleure utilisation du serveur.
Ce que vous observez est l’un des effets de ce que nous pouvons appeler « le levage lourd du HTTP ». Dans cet article de blog, nous étudions le fonctionnement de HTTP et la manière dont les serveurs HTTP courants traitent les transactions HTTP. Nous examinons certains des problèmes de performances qui peuvent survenir et voyons comment le modèle piloté par les événements de NGINX en fait un proxy accélérateur très efficace pour ces serveurs HTTP. Avec NGINX, vous pouvez transformer vos performances réelles afin qu’elles reviennent au niveau de vos références locales.
Pour obtenir des conseils sur le réglage de Linux et NGINX pour améliorer la vitesse et l'évolutivité de vos applications, consultez Tuning NGINX for Performance sur notre blog.
Les connexions HTTP keepalive sont une fonctionnalité de performance nécessaire qui réduit la latence et permet aux pages Web de se charger plus rapidement.
HTTP est un protocole simple basé sur du texte. Si vous ne l’avez pas encore fait, jetez un œil à la sortie d’un outil de débogage HTTP tel que celui de votre navigateur Web et vérifiez la structure standard de la requête et de la réponse :
Dans son implémentation la plus simple, un client HTTP crée une nouvelle connexion TCP au serveur de destination, écrit la requête et reçoit la réponse. Le serveur ferme ensuite la connexion TCP pour libérer les ressources.
Ce mode de fonctionnement peut s'avérer très inefficace, notamment pour les pages Web complexes comportant un grand nombre d'éléments ou lorsque les liaisons réseau sont lentes. La création d’une nouvelle connexion TCP nécessite une « négociation à trois », et sa suppression implique également une procédure d’arrêt à deux voies. Créer et fermer à plusieurs reprises des connexions TCP, une pour chaque message, revient à raccrocher et à recomposer le numéro après que chaque personne a parlé lors d'une conversation téléphonique.
HTTP utilise un mécanisme appelé connexions keepalive pour maintenir ouverte la connexion TCP entre le client et le serveur une fois une transaction HTTP terminée. Si le client doit effectuer une autre transaction HTTP, il peut utiliser la connexion keepalive inactive plutôt que de créer une nouvelle connexion TCP.
Les clients ouvrent généralement un certain nombre de connexions TCP simultanées à un serveur et effectuent des transactions de maintien en activité sur chacune d'entre elles. Ces connexions restent ouvertes jusqu'à ce que le client ou le serveur décide qu'elles ne sont plus nécessaires, généralement en raison d'un délai d'inactivité.
Les navigateurs Web modernes ouvrent généralement 6 à 8 connexions keepalive et les maintiennent ouvertes pendant plusieurs minutes avant de les expirer. Les serveurs Web peuvent être configurés pour expirer ces connexions et les fermer plus tôt.
Si de nombreux clients utilisent des keepalives HTTP et que le serveur Web présente une limite de concurrence ou un problème d'évolutivité, les performances chutent une fois cette limite atteinte.
L’approche ci-dessus est conçue pour offrir les meilleures performances possibles à un client individuel. Malheureusement, dans un scénario de type « tragédie des biens communs », si tous les clients fonctionnent de cette manière, cela peut avoir un effet néfaste sur les performances de nombreux serveurs Web et applications Web courants.
La raison est que de nombreux serveurs ont une limite de concurrence fixe. Par exemple, dans les configurations courantes, le serveur HTTP Apache ne peut traiter qu'un nombre limité de connexions TCP simultanées : 150 avec le module multitraitement des travailleurs (MPM) et 256 avec le MPM prefork . Chaque connexion HTTP keepalive inactive consomme l'un de ces emplacements de concurrence, et une fois que tous les emplacements sont occupés, le serveur ne peut plus accepter de connexions HTTP.
La sagesse conventionnelle dit de désactiver les keepalives sur le serveur Web ou de les limiter à une durée de vie très courte. Ils fournissent un vecteur très simple pour les attaques par déni de service SlowHTTPTest et Slowloris (pour une solution rapide, voir Protection contre le déni de service Keep-Dead sur serverfault.com).
De plus, ces serveurs Web et d’applications allouent généralement un thread ou un processus du système d’exploitation pour chaque connexion. Une connexion TCP est un objet de système d’exploitation très léger, mais un thread ou un processus est très lourd. Les threads et les processus nécessitent de la mémoire, ils doivent être gérés activement par le système d'exploitation et le « changement de contexte » entre les threads ou les processus consomme du CPU. Attribuer à chaque connexion son propre thread ou processus est extrêmement inefficace.
Le grand nombre de connexions client simultanées et l'affectation d'un thread ou d'un processus à chaque connexion produisent le phénomène connu sous le nom de « HTTP Heavy Lifting », où un effort disproportionné est nécessaire pour traiter une transaction HTTP légère.
Il ne faut pas beaucoup de clients pour épuiser la limite de concurrence dans de nombreux serveurs Web et d’applications contemporains.
Si un client ouvre 8 connexions TCP et maintient chacune d'elles active pendant 15 secondes après la dernière utilisation, le client consomme 8 emplacements de concurrence pendant 15 secondes. Si les clients arrivent sur votre site Web au rythme de 1 par seconde, 120 emplacements de concurrence sont continuellement occupés par des connexions keepalive inactives. Si le débit est de 2 clients par seconde, 240 emplacements de simultanéité sont occupés. Une fois les créneaux épuisés, les nouveaux clients ne peuvent pas se connecter tant que les connexions existantes n'ont pas expiré.
Cela peut entraîner des niveaux de service très inégaux. Les clients qui acquièrent avec succès une connexion Keepalive peuvent parcourir votre service à volonté. Les clients qui tentent de se connecter alors que tous les créneaux de simultanéité sont occupés sont bloqués et doivent attendre dans une file d'attente.
Ces problèmes ne se manifestent que dans les réseaux lents avec de nombreux clients. Ils n’apparaissent pas lors d’une analyse comparative avec un seul client sur un réseau local rapide.
Il existe plusieurs raisons pour lesquelles vous ne verrez peut-être pas ces effets dans un benchmark.
Notez que la plupart des outils d’analyse comparative ne rendent compte que des transactions réussies. Les connexions bloquées en raison d'un épuisement des ressources peuvent ne pas être signalées ou peuvent sembler ne représenter qu'une infime fraction des connexions réussies. Cela masque la véritable nature du problème du trafic dans le monde réel.
Tout serveur Web ou d’application basé sur un thread ou un processus est vulnérable aux limitations de concurrence.
Ce problème est inhérent à toute plate-forme Web ou applicative qui attribue un thread ou un processus à chaque connexion. Ce n’est pas facile à détecter dans un environnement de référence optimisé, mais cela se manifeste par de mauvaises performances et une utilisation excessive du processeur dans un environnement réel.
Il existe plusieurs mesures que vous pouvez prendre pour résoudre ce problème :
NGINX utilise une architecture différente qui ne souffre pas des problèmes de concurrence décrits ci-dessus. Il transforme les connexions client lentes en connexions optimisées de type benchmark pour extraire les meilleures performances de vos serveurs.
NGINX utilise un modèle piloté par événements hautement efficace pour gérer les connexions.
Chaque processus NGINX peut gérer plusieurs connexions en même temps. Lorsqu'une nouvelle connexion est acceptée, la surcharge est très faible (elle consiste en un nouveau descripteur de fichier et un nouvel événement à interroger), contrairement au modèle par processus ou par thread décrit ci-dessus. NGINX dispose d'une boucle d'événements très efficace :
Cela permet à chaque processus NGINX de s'adapter facilement à des dizaines, des milliers ou des centaines de milliers de connexions simultanément.
NGINX transmet ensuite les requêtes au serveur en amont, en utilisant un pool local de connexions keepalive. Vous ne subissez pas de surcharge liée à l’ouverture et à la fermeture des connexions TCP, et les piles TCP s’adaptent rapidement à la taille de fenêtre optimale et aux paramètres de nouvelle tentative. L'écriture des requêtes et la lecture des réponses sont beaucoup plus rapides sur le réseau local optimisé :
L’effet net est que le serveur en amont se retrouve à communiquer avec un seul client local (NGINX) sur un réseau rapide, et c’est un client qui utilise de manière optimale les connexions HTTP keepalive pour minimiser la configuration de la connexion sans maintenir les connexions ouvertes inutilement. Cela remet le serveur dans son environnement optimal, de type benchmark.
Avec NGINX agissant comme un proxy HTTP, vous voyez :
La suppression du fardeau du HTTP n’est qu’une des mesures de transformation des performances que NGINX peut apporter à votre infrastructure d’application surchargée.
La fonctionnalité de mise en cache HTTP de NGINX peut mettre en cache les réponses des serveurs en amont, en suivant la sémantique de cache standard pour contrôler ce qui est mis en cache et pendant combien de temps. Si plusieurs clients demandent la même ressource, NGINX peut répondre depuis son cache et ne pas surcharger les serveurs en amont avec des demandes en double.
NGINX peut également décharger d’autres opérations du serveur en amont. Vous pouvez décharger les opérations de compression de données pour réduire l'utilisation de la bande passante, centraliser le chiffrement et le déchiffrement SSL/TLS , effectuer l'authentification initiale du client (par exemple, avec l'authentification de base HTTP , les sous-requêtes vers des serveurs d'authentification externes et les jetons Web JSON ) et appliquer toutes sortes de règles pour limiter le trafic lorsque cela est nécessaire.
Enfin, n'oubliez pas que contrairement à d'autres proxys accélérateurs, équilibreurs de charge ou contrôleurs de distribution d'applications (ADC), NGINX est également un serveur Web complet . Vous pouvez utiliser NGINX pour diffuser du contenu statique , transférer le trafic vers des serveurs d'applications pour Java, PHP, Python, Ruby et d'autres langages, diffuser des médias (audio et vidéo) , intégrer des systèmes d'authentification et de sécurité et même répondre directement aux transactions à l'aide de règles intégrées dans la configuration NGINX.
Sans limitations de performances intégrées, NGINX et NGINX Plus tirent pleinement parti du matériel sur lequel vous les déployez, maintenant et à l’avenir.
Pour essayer NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation .
« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."