Nous avons beaucoup écrit sur la façon dont vous pouvez utiliser NGINX Plus et NGINX Open Source pour équilibrer la charge de vos sites Web et applications pour une disponibilité et une fiabilité optimales. L'équilibrage de charge est un outil fondamental pour améliorer les performances des applications , fournir des applications à grande échelle et déployer des conteneurs et des microservices .
Nous avons précédemment expliqué comment vous pouvez déployer NGINX Plus dans le centre de données (peut-être aux côtés des contrôleurs de distribution d'applications hérités), dans des conteneurs et dans des environnements cloud, notamment Amazon Web Services (AWS), Google Cloud Platform et Microsoft Azure .
Dans cet article, nous nous concentrerons sur les techniques d'équilibrage de charge (également appelées méthodes ou algorithmes d'équilibrage de charge) dans NGINX Plus et NGINX, en offrant quelques conseils sur la façon de choisir la bonne méthode pour différents cas d'utilisation. NGINX fournit quatre techniques d'équilibrage de charge ( Round Robin , Hash , IP Hash et Least Connections ), et NGINX Plus en ajoute une autre ( Least Time ). Toutes les méthodes de trafic HTTP sont également disponibles pour TCP (et UDP, dans NGINX Plus Release 9 et versions ultérieures), à l'exception du hachage IP.
[ Éditeur – NGINX Plus R16 et NGINX Open Source 1.15.1 ont introduit Random with Two Choices comme algorithme d'équilibrage de charge supplémentaire. Pour une discussion, voir NGINX et l'algorithme d'équilibrage de charge « Power of Two Choices » sur notre blog.]
Nous supposerons que vous connaissez les bases de la configuration de l’équilibrage de charge, mais vous pouvez consulter ces ressources si vous souhaitez vous rafraîchir la mémoire :
Par souci de simplicité, nous nous concentrerons sur l'équilibrage de charge HTTP, que vous configurez dans le contexte http
. L'équilibrage de charge TCP est configuré dans le contexte du flux
(comme l'équilibrage de charge UDP dans NGINX Plus Release 9 et versions ultérieures). Bien que les équilibreurs de charge HTTP et TCP/UDP présentent une parité de fonctionnalités, les directives et paramètres disponibles diffèrent quelque peu en raison de différences inhérentes entre les protocoles ; pour plus de détails, consultez la documentation sur les modules Upstream pour HTTP et TCP/UDP .
Vous activez l’équilibrage de charge avec deux blocs de configuration, que nous allons afficher sous leur forme de base, sans paramètres facultatifs ni fonctionnalités auxiliaires :
Le bloc serveur
définit un serveur virtuel qui écoute le trafic avec les caractéristiques que vous définissez et le transmet à un groupe nommé de serveurs en amont. Dans nos exemples, le serveur virtuel écoute sur le port par défaut (80) le trafic HTTP envoyé à www.example.com et le transmet au groupe de serveurs en amont appelé backend . Ce bloc est le même dans tous nos exemples.
serveur { nom_serveur www.exemple.com;
emplacement / {
proxy_pass http://backend;
}
}
(NGINX Plus et NGINX peuvent également équilibrer la charge des serveurs backend FastCGI, memcached, SCGI et uwsgi. Remplacez proxy_pass
par la directive appropriée – fastcgi_pass
, memcached_pass
, scgi_pass
ou uwsgi_pass
.)
Le bloc en amont
nomme un groupe en amont et répertorie les serveurs qui lui appartiennent, identifiés par le nom d’hôte, l’adresse IP ou le chemin du socket de domaine UNIX. Dans nos exemples, le groupe en amont appelé backend comprend trois serveurs : web1 , web2 et web3 .
Le bloc en amont
est l'endroit où vous spécifiez la technique d'équilibrage de charge. Nous le soulignerons donc dans les sections suivantes. À titre d’exemple, voici le bloc de la méthode par défaut, Round Robin :
backend en amont { serveur web1 ;
serveur web2 ;
serveur web3 ;
}
Round Robin est la technique d'équilibrage de charge par défaut pour NGINX Plus et NGINX. L'équilibreur de charge parcourt la liste des serveurs en amont dans l'ordre, en attribuant la prochaine demande de connexion à chacun d'eux à tour de rôle.
Étant donné l'exemple de configuration suivant du groupe en amont du backend , l'équilibreur de charge envoie les trois premières demandes de connexion à web1 , web2 et web3 dans l'ordre, la quatrième à web1 , la cinquième à web2 , et ainsi de suite.
backend en amont { serveur web1 ;
serveur web2 ;
serveur web3 ;
}
serveur {
nom_serveur www.exemple.com ;
emplacement / {
proxy_pass http://backend ;
}
}
Avec la méthode Hash, pour chaque demande, l'équilibreur de charge calcule un hachage basé sur la combinaison de texte et de variables NGINX que vous spécifiez, et associe le hachage à l'un des serveurs. Il envoie toutes les requêtes avec ce hachage à ce serveur, donc cette méthode établit un type de base de persistance de session .
Dans l'exemple suivant, la directive hash
utilise le schéma ( http ou https ) et l'URI complet de la requête comme base pour le hachage :
backend en amont { hash $scheme$request_uri; serveur web1; serveur web2; serveur web3; } serveur { nom_serveur www.example.com; emplacement / { proxy_pass http://backend; } }
IP Hash (disponible pour HTTP uniquement) est une variante prédéfinie de la méthode Hash, dans laquelle le hachage est basé sur l'adresse IP du client. Vous le définissez avec la directive ip_hash
.
backend en amont { ip_hash ; serveur web1 ; serveur web2 ; serveur web3 ; } serveur { nom_serveur www.exemple.com ; emplacement / { proxy_pass http://backend ; } }
Si le client possède une adresse IPv6, le hachage est basé sur l'adresse entière. S'il possède une adresse IPv4, le hachage est basé uniquement sur les trois premiers octets de l'adresse. Ceci est conçu pour optimiser les clients FAI auxquels des adresses IP sont attribuées de manière dynamique à partir d'une plage de sous-réseaux (/24). En cas de redémarrage ou de reconnexion, l’adresse du client change souvent pour une autre dans la plage réseau /24, mais la connexion représente toujours le même client, il n’y a donc aucune raison de modifier le mappage vers le serveur.
Toutefois, si la majorité du trafic vers votre site provient de clients du même réseau /24, le hachage IP n'a pas de sens car il mappe tous les clients sur le même serveur. Dans ce cas (ou si vous souhaitez hacher les quatre octets pour une autre raison), utilisez plutôt la méthode Hash avec la variable $remote_addr
.
hachage $remote_addr;
Avec la méthode Least Connections, l'équilibreur de charge compare le nombre actuel de connexions actives dont il dispose à chaque serveur et envoie la demande au serveur avec le moins de connexions. Vous le configurez avec la directive least_conn
.
backend en amont { least_conn ; serveur web1 ; serveur web2 ; serveur web3 ; } serveur { nom_serveur www.example.com ; emplacement / { proxy_pass http://backend ; } }
Avec la méthode Least Time (disponible uniquement dans NGINX Plus), l'équilibreur de charge combine mathématiquement deux mesures pour chaque serveur (le nombre actuel de connexions actives et un temps de réponse moyen pondéré pour les requêtes passées) et envoie la requête au serveur avec la valeur la plus basse.
Votre choix de paramètre sur la directive least_time
contrôle lequel des deux temps de réponse est suivi : soit le temps de réception de l'en-tête de réponse ( header
), soit le temps de réception de la réponse complète ( last_byte
).
backend en amont { least_time (header | last_byte) ; serveur web1 ;
serveur web2 ; serveur web3 ; } serveur { nom_serveur www.example.com ; emplacement / { proxy_pass http://backend ; } }
Remarques :
Pour l'équilibrage de charge TCP et UDP (dans le contexte du flux
), vous pouvez choisir parmi trois types de temps de réponse avec ces paramètres pour la directive least_time
:
connect
– Il est temps de se connecter au serveur en amontfirst_byte
– Heure de réception du premier octet des données de réponselast_byte
– Heure de réception du dernier octet des données de réponsePour le trafic HTTP et TCP/UDP, dans NGINX Plus R12 et versions ultérieures, ajoutez le paramètre inflight
pour inclure les connexions incomplètes dans chaque métrique ; ces connexions sont incluses par défaut dans les versions antérieures.
Alors, comment savoir quelle technique d’équilibrage de charge est la meilleure pour votre site Web ou votre application ?
Les modèles de trafic varient tellement d’un site à l’autre – et même au sein d’un même site à différents moments de la journée – qu’il n’est pas logique de baser le choix de la technique d’équilibrage de charge sur une seule caractéristique (comme un trafic en rafales ou régulier, des connexions de courte durée ou de longue durée, etc.). Cela dit, nous examinerons les avantages et les inconvénients de chaque méthode pour vous aider à réduire la gamme de choix à prendre en compte.
Quel que soit le sous-ensemble de méthodes d’équilibrage de charge que vous envisagez, nous vous encourageons à les tester pour voir celle qui fonctionne le mieux pour votre trafic. « Meilleur » signifie généralement le délai le plus court pour répondre aux clients, mais vos critères peuvent être différents.
Les outils de gestion des performances des applications sont très pratiques pour ce type de test : vous pouvez créer des écrans personnalisés avec des graphiques pour chacun des serveurs du groupe en amont, ce qui permet de les comparer en temps réel à mesure que les valeurs changent pendant le test. Plusieurs APM proposent des plug-ins personnalisés pour NGINX Plus et NGINX, notamment AppDynamics , Datadog , Dynatrace et New Relic .
Les tests sont plus simples si tous les serveurs ont la même capacité. Dans le cas contraire, vous devez définir les poids des serveurs afin que les machines avec plus de capacité reçoivent plus de demandes. Voir Définition des poids lorsque les serveurs ne sont pas identiques ci-dessous.
Voici quelques paramètres à vérifier pendant les tests :
404
( Fichier
non
trouvé
), par exemple, le serveur renvoie probablement l'erreur beaucoup plus rapidement qu'il ne pourrait fournir le fichier réel s'il existait. Avec les algorithmes d’équilibrage de charge Least Connections et Least Time, cela peut amener l’équilibreur de charge à favoriser un serveur qui ne fonctionne pas bien.Examinons maintenant les avantages et les inconvénients de chaque technique d’équilibrage de charge et décrivons certains cas d’utilisation pour lesquels elles sont particulièrement adaptées. Nous les aborderons par ordre croissant d’adéquation à la majorité des cas d’utilisation. En guise d'aperçu rapide : nous considérons que les connexions minimales (et, pour NGINX Plus, le temps minimal) sont les meilleurs choix pour la plus large gamme de cas d'utilisation.
Les techniques d’équilibrage de charge Hash et IP Hash créent une association fixe entre un type donné de demande client (capturée dans la valeur de hachage) et un certain serveur. Vous reconnaîtrez peut-être cela comme la persistance de session : toutes les requêtes avec une valeur de hachage donnée vont toujours au même serveur.
Le plus gros inconvénient de ces méthodes est qu’elles ne garantissent pas la répartition des requêtes en nombre égal sur les serveurs, et encore moins l’équilibrage uniforme de la charge. L'algorithme de hachage divise uniformément l'ensemble de toutes les valeurs de hachage possibles en « buckets », un pour chaque serveur du groupe en amont, mais il n'y a aucun moyen de prédire si les requêtes qui se produisent réellement auront des hachages uniformément répartis. Supposons, par exemple, que dix clients accèdent à un site et que l'algorithme de hachage IP associe le hachage de sept adresses IP à web1 , une à web2 et deux à web3 . Le serveur web1 finit par recevoir plus de deux fois plus de requêtes que les autres serveurs réunis.
Il est donc logique d’utiliser Hash ou IP Hash lorsque l’avantage du maintien des sessions l’emporte sur les effets potentiellement néfastes d’une charge déséquilibrée. Il s'agit de la seule forme de persistance de session disponible dans NGINX. NGINX Plus fournit trois autres mécanismes de persistance de session qui sont plus sophistiqués et fonctionnent en combinaison avec un équilibrage de charge réel (vous les configurez avec la directive sticky
). Mais vous pouvez choisir Hash ou IP Hash même avec NGINX Plus, car les trois mécanismes ne fonctionnent pas dans les cas suivants :
Le navigateur ou l’application cliente n’accepte pas les cookies et l’application ne dispose pas de moyen de fonctionner avec les mécanismes de persistance de session sans cookies. Utilisez la méthode de hachage IP pour associer chaque client (en particulier son adresse IP) à un serveur particulier.
Vous souhaitez envoyer des requêtes pour une URL donnée au même serveur à chaque fois, pour profiter de la mise en cache sur le serveur lui-même. Utilisez la méthode Hash avec la variable $request_uri
pour récupérer le fichier à partir du même serveur à chaque fois.
Par exemple, supposons que vous sachiez que la diffusion d'un certain fichier .php nécessite plusieurs appels de base de données chronophages, mais que les données récupérées ne changent pas souvent et peuvent donc être mises en cache. Si vous dirigez toutes les requêtes du fichier vers le même serveur, seul le premier client subit un long délai en raison des appels à la base de données. Pour tous les clients suivants, les données sont rapidement récupérées à partir du cache. Un autre avantage est qu’un seul serveur doit mettre en cache cet ensemble particulier de données. Étant donné que vous ne finissez pas par dupliquer la mise en cache des mêmes données sur chaque serveur, vous pouvez utiliser des caches plus petits.
Il existe quelques cas où le hachage IP (et le hachage lorsque l'adresse IP du client est dans la clé) ne fonctionne pas :
Les hachages sont déterministes (l’algorithme de hachage donne les mêmes résultats à chaque fois). Cela a quelques effets secondaires positifs : toutes les instances NGINX Plus ou NGINX d’un déploiement équilibrent la charge des requêtes exactement de la même manière, et le mappage hachage-serveur persiste après les redémarrages de l’équilibreur de charge. (Il est en fait recalculé après le redémarrage, mais comme le résultat est toujours le même, il persiste effectivement.)
D’autre part, changer l’ensemble des serveurs en amont force généralement le recalcul d’au moins certains des mappages, interrompant ainsi la persistance de la session. Vous pouvez réduire quelque peu le nombre de mappages recalculés :
cohérent
dans la directive hash
; NGINX Plus utilise l'algorithme de hachage ketama , ce qui entraîne moins de remappage.Pour la méthode IP Hash, avant de supprimer temporairement un serveur du groupe en amont, ajoutez le paramètre down
à sa directive serveur
, comme pour web2 dans l'exemple suivant. Les mappages ne sont pas recalculés, en supposant que le serveur reviendra bientôt en service.
backend en amont { ip_hash; serveur web1; serveur web2 en panne ; serveur web3; }
Comme indiqué précédemment, Round Robin est la méthode d'équilibrage de charge par défaut dans NGINX Plus et NGINX. Cela en fait certainement la méthode la plus simple à choisir – vous n'avez rien à configurer au-delà du groupe en amont lui-même.
Le consensus général est que Round Robin fonctionne mieux lorsque les caractéristiques des serveurs et des requêtes sont peu susceptibles d'entraîner une surcharge de certains serveurs par rapport à d'autres. Certaines des conditions sont :
Round Robin est particulièrement adapté aux scénarios de test, car il garantit que les requêtes sont réparties sur tous les serveurs et en nombre égal (ou dans la proportion pondérée appropriée). Certaines autres méthodes ne répartissent pas toujours le trafic de manière uniforme lorsque le volume est faible, ce qui peut fausser les résultats des tests.
La nature uniforme de la distribution peut également révéler si les caches fonctionnent bien et à pleine capacité : comme il n’existe aucun moyen avec Round Robin d’envoyer des requêtes pour un fichier donné au même serveur, chaque serveur est susceptible de finir par servir et mettre en cache une large gamme de fichiers (et généralement de nombreux fichiers identiques à ceux de ses homologues), ce qui augmente la probabilité que le cache se remplisse.
Enfin, la distribution initiale uniforme permet de découvrir les problèmes de persistance de session dans NGINX Plus (comme configuré avec la directive sticky
).
Comme nous l’avons mentionné ci-dessus, Least Connections est la technique d’équilibrage de charge la plus adaptée à la plus large gamme de cas d’utilisation, et en particulier pour le trafic de production. Ceci est confirmé par des témoignages anecdotiques de nos clients. Ses performances sont stables et prévisibles.
Least Connections répartit également efficacement la charge de travail sur les serveurs en fonction de leur capacité. Un serveur plus puissant répond aux requêtes plus rapidement, il est donc probable qu'à tout moment, il y ait un nombre plus petit de connexions encore en cours de traitement (ou même en attente de démarrage du traitement) qu'un serveur avec moins de capacité. Least Connections envoie chaque requête au serveur avec le plus petit nombre de connexions actuelles et est donc plus susceptible d'envoyer des requêtes à des serveurs puissants. (La définition des pondérations entraîne néanmoins une distribution encore plus efficace des requêtes, comme décrit dans Définition des pondérations lorsque les serveurs ne sont pas identiques ci-dessous.)
Vous pouvez considérer Least Time (NGINX Plus uniquement) comme une version plus sensible de Least Connections. En incluant le temps de réponse moyen, il prend en compte l’historique récent des performances du serveur (il s’agit en fait d’une moyenne mobile pondérée de manière exponentielle, de sorte que les temps de réponse plus anciens influencent moins la moyenne que les temps de réponse plus récents).
Le Least Time est particulièrement adapté lorsque les serveurs en amont ont des temps de réponse moyens très différents. Si, par exemple, vous disposez de serveurs dans différents centres de données à des fins de reprise après sinistre, Least Time a tendance à envoyer davantage de requêtes aux serveurs locaux, car ils répondent plus rapidement. Un autre cas d’utilisation est celui des environnements cloud, où les performances du serveur sont souvent très imprévisibles.
Nous avons mentionné à plusieurs reprises l’importance de définir les poids des serveurs lorsque les serveurs du groupe en amont ont des capacités différentes. C'est particulièrement important pour l'équilibreur de charge Round Robin, qui envoie par ailleurs le même nombre de requêtes à chaque serveur. Il est probable que cela entraîne une surcharge d’un serveur moins puissant tandis qu’un serveur plus puissant reste partiellement inactif.
Pour définir les poids, incluez le paramètre de poids
sur une ou plusieurs directives de serveur
dans le bloc en amont
. La valeur par défaut est 1.
Vous pouvez réfléchir à l’effet de la définition de pondérations pour les différentes techniques d’équilibrage de charge de la manière suivante. Gardez à l’esprit que les descriptions sont conceptuellement correctes, mais l’implémentation dans le code NGINX Plus n’utilise pas nécessairement les opérations mathématiques indiquées. Voici le groupe en amont de nos exemples :
backend en amont { serveur web1 poids=6 ;
serveur web2 poids=3 ;
serveur web3 ;
}
Round Robin – Chaque serveur reçoit le pourcentage des requêtes entrantes égal à son poids divisé par la somme des poids. Dans notre exemple, sur dix requêtes, web1 en reçoit six (60 %), web2 en reçoit trois (30 %) et web3 en reçoit une (10 %).
Hachage et hachage IP – Rappelons que sans pondération, l’algorithme de hachage divise uniformément l’ensemble de toutes les valeurs de hachage possibles en « seaux », un pour chaque serveur du groupe en amont. Avec les poids, il additionne les poids, divise l'ensemble des hachages possibles entre ce nombre de buckets et associe chaque serveur au nombre de buckets équivalent à son poids.
Dans notre exemple, il y a dix buckets, chacun contenant 10 % des hachages possibles. Six buckets (60 % des hachages possibles) sont associés à web1 , trois buckets (30 %) à web2 et un bucket (10 %) à web3 .
Moins de connexions et moins de temps – Nous avons mentionné précédemment que même sans pondération, ces algorithmes sont assez efficaces pour répartir la charge de travail sur les serveurs en fonction de leur capacité. La fixation de poids améliore encore davantage leurs performances à cet égard.
Rappelons que Least Connections et Least Time envoient chaque requête au serveur avec le « score » le plus bas (nombre de connexions ou une combinaison mathématique de connexions et de temps, respectivement). Lorsque vous attribuez des pondérations, l’équilibreur de charge divise le score de chaque serveur par son poids et envoie à nouveau la demande au serveur ayant la valeur la plus basse.
Voici un exemple pour les connexions minimales avec nos poids d'échantillon et le nombre indiqué de connexions actives : le score de 100 de web1 est le plus bas et il obtient la demande même si son nombre de connexions de 600 est 1,5 fois celui de web2 et plus de 4 fois celui de web3 .
Après avoir examiné les avantages et les inconvénients des techniques d’équilibrage de charge disponibles dans NGINX Plus et NGINX, nous considérons que les connexions minimales (et, pour NGINX Plus, le temps minimal) sont les plus adaptées à la plus large gamme de cas d’utilisation. Mais il est important que vous testiez plusieurs méthodes dans votre déploiement, car la combinaison unique de caractéristiques du trafic et du serveur peut rendre une autre méthode plus adaptée à vos besoins.
Pour essayer vous-même l'équilibrage de charge NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation.
Nous aimerions connaître vos expériences en matière d’équilibrage de charge dans différents cas d’utilisation. Veuillez les ajouter à la section commentaires ci-dessous.
« 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."