Architectures d'équilibrage de charge serveur, partie 1: équilibrage de charge au niveau du transport

Les batteries de serveurs atteignent une évolutivité et une disponibilité élevées grâce à l'équilibrage de la charge des serveurs, une technique qui fait apparaître la batterie de serveurs aux clients comme un serveur unique. Dans cet article en deux parties, Gregor Roth explore les architectures d'équilibrage de charge des serveurs, en se concentrant sur les solutions open source. La partie 1 couvre les principes de base de l'équilibrage de la charge du serveur et présente les avantages et les inconvénients de l'équilibrage de charge du serveur au niveau du transport. La partie 2 couvre les architectures d'équilibrage de charge des serveurs au niveau des applications, qui répondent à certaines des limites des architectures décrites dans la partie 1.

La barrière à l'entrée pour de nombreuses sociétés Internet est faible. Toute personne ayant une bonne idée peut développer une petite application, acheter un nom de domaine et configurer quelques serveurs sur PC pour gérer le trafic entrant. L'investissement initial est faible, le risque de démarrage est donc minime. Mais une infrastructure bon marché réussie peut rapidement devenir un problème sérieux. Un serveur unique qui gère toutes les demandes entrantes peut ne pas avoir la capacité de gérer des volumes de trafic élevés une fois que l'entreprise devient populaire. Dans de telles situations, les entreprises commencent souvent à se développer : elles mettent à niveau l'infrastructure existante en achetant un boîtier plus grand avec plus de processeurs ou en ajoutant plus de mémoire pour exécuter les applications.

La mise à l'échelle, cependant, n'est qu'une solution à court terme. Et c'est une approche limitée car le coût de la mise à niveau est disproportionnellement élevé par rapport aux gains de capacité du serveur. Pour ces raisons, la plupart des sociétés Internet qui réussissent suivent une approche de mise à l'échelle . Les composants d'application sont traités comme plusieurs instances sur des batteries de serveurs, qui sont basées sur du matériel et des systèmes d'exploitation à faible coût. À mesure que le trafic augmente, des serveurs sont ajoutés.

L'approche de la batterie de serveurs a ses propres exigences. Du côté logiciel, vous devez concevoir des applications afin qu'elles puissent s'exécuter en tant qu'instances multiples sur différents serveurs. Pour ce faire, vous divisez l'application en composants plus petits qui peuvent être déployés indépendamment. C'est trivial si les composants de l'application sont sans état. Étant donné que les composants ne conservent aucun état transactionnel, chacun d'eux peut gérer les mêmes demandes de la même manière. Si plus de puissance de traitement est requise, il vous suffit d'ajouter plus de serveurs et d'installer les composants d'application.

Un problème plus difficile se pose lorsque les composants de l'application sont avec état. Par exemple, si le composant d'application contient des données de panier, une demande entrante doit être acheminée vers une instance de composant d'application qui contient les données de panier de ce demandeur. Plus loin dans cet article, j'expliquerai comment gérer ces données de session d'application dans un environnement distribué. Cependant, pour réduire la complexité, la plupart des systèmes d'application basés sur Internet tentent d'éviter autant que possible les composants d'application avec état.

Côté infrastructure, la charge de traitement doit être répartie entre le groupe de serveurs. C'est ce qu'on appelle l'équilibrage de la charge du serveur. Les technologies d'équilibrage de charge concernent également d'autres domaines, par exemple la répartition du travail entre les composants tels que les liaisons réseau, les processeurs ou les disques durs. Cet article se concentre sur l'équilibrage de la charge du serveur.

Disponibilité et évolutivité

L'équilibrage de la charge du serveur distribue les demandes de service sur un groupe de serveurs réels et donne à ces serveurs l'apparence d'un seul gros serveur pour les clients. Souvent, des dizaines de serveurs réels se trouvent derrière une URL qui implémente un seul service virtuel.

Comment cela marche-t-il? Dans une architecture d'équilibrage de charge serveur largement utilisée, la requête entrante est dirigée vers un équilibreur de charge serveur dédié qui est transparent pour le client. En fonction de paramètres tels que la disponibilité ou la charge actuelle du serveur, l'équilibreur de charge décide quel serveur doit gérer la demande et la transmet au serveur sélectionné. Pour fournir à l'algorithme d'équilibrage de charge les données d'entrée requises, l'équilibreur de charge récupère également des informations sur l'intégrité et la charge des serveurs pour vérifier qu'ils peuvent répondre au trafic. La figure 1 illustre cette architecture d'équilibrage de charge classique.

L'architecture de répartition de charge illustrée à la figure 1 n'est qu'une des nombreuses approches. Pour décider quelle solution d'équilibrage de charge est la meilleure pour votre infrastructure, vous devez tenir compte de la disponibilité et de l' évolutivité .

La disponibilité est définie par le temps de fonctionnement - le temps entre les pannes. (Le temps d'arrêt est le temps nécessaire pour détecter la panne, la réparer, effectuer la récupération requise et redémarrer les tâches.) Pendant la durée de fonctionnement, le système doit répondre à chaque demande dans un délai prédéterminé et bien défini. Si ce délai est dépassé, le client voit cela comme un dysfonctionnement du serveur. La haute disponibilité, fondamentalement, est la redondance dans le système: si un serveur tombe en panne, les autres prennent en charge la charge du serveur défaillant de manière transparente. La défaillance d'un serveur individuel est invisible pour le client.

L'évolutivité signifie que le système peut servir un seul client, ainsi que des milliers de clients simultanés, en répondant aux exigences de qualité de service telles que le temps de réponse. Sous une charge accrue, un système hautement évolutif peut augmenter le débit de manière presque linéaire en proportion de la puissance des ressources matérielles supplémentaires.

Dans le scénario de la figure 1, une évolutivité élevée est atteinte en distribuant la demande entrante sur les serveurs. Si la charge augmente, des serveurs supplémentaires peuvent être ajoutés, tant que l'équilibreur de charge ne devient pas le goulot d'étranglement. Pour atteindre la haute disponibilité, l'équilibreur de charge doit surveiller les serveurs pour éviter de transférer les demandes vers des serveurs surchargés ou morts. En outre, l'équilibreur de charge lui-même doit également être redondant. J'aborderai ce point plus loin dans cet article.

Techniques d'équilibrage de la charge du serveur

En général, les solutions d'équilibrage de la charge des serveurs sont de deux types principaux:

  • L' équilibrage de charge au niveau du transport - comme l'approche basée sur DNS ou l'équilibrage de charge au niveau TCP / IP - agit indépendamment de la charge utile de l'application.
  • L' équilibrage de charge au niveau de l'application utilise la charge utile de l'application pour prendre des décisions d'équilibrage de charge.

Les solutions d'équilibrage de charge peuvent être classées en équilibreurs de charge logiciels et en équilibreurs de charge matériels. Les équilibreurs de charge basés sur le matériel sont des boîtiers matériels spécialisés qui incluent des circuits intégrés spécifiques à une application (ASIC) personnalisés pour une utilisation particulière. Les ASIC permettent une transmission à grande vitesse du trafic réseau sans la surcharge d'un système d'exploitation à usage général. Les équilibreurs de charge matériels sont souvent utilisés pour l'équilibrage de charge au niveau du transport. En général, les équilibreurs de charge matériels sont plus rapides que les solutions logicielles. Leur inconvénient est leur coût.

Contrairement aux équilibreurs de charge matériels, les équilibreurs de charge logiciels fonctionnent sur des systèmes d'exploitation standard et des composants matériels standard tels que des PC. Les solutions logicielles s'exécutent soit dans un nœud matériel d'équilibrage de charge dédié, comme illustré à la figure 1, soit directement dans l'application.

Équilibrage de charge basé sur DNS

L'équilibrage de charge basé sur DNS représente l'une des premières approches d'équilibrage de charge du serveur. Le système de noms de domaine (DNS) d'Internet associe des adresses IP à un nom d'hôte. Si vous saisissez un nom d'hôte (dans le cadre de l'URL) dans votre navigateur, le navigateur demande au serveur DNS de résoudre le nom d'hôte en une adresse IP.

L'approche basée sur le DNS est basée sur le fait que DNS permet d'attribuer plusieurs adresses IP (vrais serveurs) à un seul nom d'hôte, comme indiqué dans l'exemple de recherche DNS du listing 1.

Liste 1. Exemple de recherche DNS

>nslookup amazon.com Server: ns.box Address: 192.168.1.1 Name: amazon.com Addresses: 72.21.203.1, 72.21.210.11, 72.21.206.5

Si le serveur DNS implémente une approche circulaire, l'ordre des adresses IP pour un hôte donné change après chaque réponse DNS. Habituellement, les clients tels que les navigateurs essaient de se connecter à la première adresse renvoyée par une requête DNS. Le résultat est que les réponses à plusieurs clients sont réparties entre les serveurs. Contrairement à l'architecture d'équilibrage de charge du serveur de la figure 1, aucun nœud matériel d'équilibrage de charge intermédiaire n'est requis.

DNS est une solution efficace pour l'équilibrage de charge global des serveurs, où la charge doit être répartie entre les centres de données situés à différents endroits. Souvent, l'équilibrage de charge de serveur global basé sur DNS est combiné avec d'autres solutions d'équilibrage de charge de serveur pour répartir la charge dans un centre de données dédié.

Bien que facile à mettre en œuvre, l'approche DNS présente de sérieux inconvénients. Pour réduire les requêtes DNS, le client a tendance à mettre en cache les requêtes DNS. Si un serveur devient indisponible, le cache client ainsi que le serveur DNS continueront à contenir une adresse de serveur morte. Pour cette raison, l'approche DNS fait peu pour implémenter la haute disponibilité.

Équilibrage de charge du serveur TCP / IP

Les équilibreurs de charge de serveur TCP / IP fonctionnent sur la commutation de couche de bas niveau. Un équilibreur de charge de serveur de bas niveau basé sur un logiciel populaire est le serveur virtuel Linux (LVS). Les vrais serveurs apparaissent au monde extérieur comme un seul serveur «virtuel». Les demandes entrantes sur une connexion TCP sont transmises aux serveurs réels par l'équilibreur de charge, qui exécute un noyau Linux patché pour inclure le code IP Virtual Server (IPVS).

Pour garantir une haute disponibilité, dans la plupart des cas, une paire de nœuds d'équilibrage de charge est configurée, avec un nœud d'équilibrage de charge en mode passif. En cas d'échec d'un équilibreur de charge, le programme de pulsation qui s'exécute sur les deux équilibreurs de charge active le nœud d'équilibrage de charge passif et lance la prise de contrôle de l'adresse IP virtuelle (VIP). Alors que le battement de cœur est responsable de la gestion du basculement entre les équilibreurs de charge, de simples scripts d'envoi / d'attente sont utilisés pour surveiller la santé des serveurs réels.

La transparence envers le client est obtenue à l'aide d'un VIP affecté à l'équilibreur de charge. Si le client émet une demande, le nom d'hôte demandé est d'abord traduit en VIP. Lorsqu'il reçoit le paquet de requête, l'équilibreur de charge décide quel serveur réel doit gérer le paquet de requête. L'adresse IP cible du paquet de demande est réécrite dans l'IP réel (RIP) du serveur réel. LVS prend en charge plusieurs algorithmes de planification pour distribuer les requêtes aux serveurs réels. Il est souvent configuré pour utiliser la planification circulaire, similaire à l'équilibrage de charge basé sur DNS. Avec LVS, la décision d'équilibrage de charge est prise au niveau TCP (couche 4 du modèle de référence OSI).

Après avoir reçu le paquet de requête, le serveur réel le gère et renvoie le paquet de réponse. Pour forcer le retour du paquet de réponse via l'équilibreur de charge, le serveur réel utilise le VIP comme route de réponse par défaut. Si l'équilibreur de charge reçoit le paquet de réponse, l'adresse IP source du paquet de réponse est réécrite avec le VIP (OSI Model Layer 3). Ce mode de routage LVS est appelé routage NAT (Network Address Translation). La figure 2 montre une implémentation LVS qui utilise le routage NAT.

LVS prend également en charge d'autres modes de routage tels que Direct Server Return. Dans ce cas, le paquet de réponse est envoyé directement au client par le serveur réel. Pour ce faire, le VIP doit également être attribué à tous les vrais serveurs. Il est important de rendre le VIP du serveur insoluble sur le réseau; sinon, l'équilibreur de charge devient inaccessible. Si l'équilibreur de charge reçoit un paquet de demande, l'adresse MAC (OSI Model Layer 2) de la demande est réécrite à la place de l'adresse IP. Le vrai serveur reçoit le paquet de requête et le traite. En fonction de l'adresse IP source, le paquet de réponse est envoyé directement au client, en contournant l'équilibreur de charge. Pour le trafic Web, cette approche peut réduire considérablement la charge de travail de l'équilibreur. En règle générale, beaucoup plus de paquets de réponse sont transférés que de paquets de demande. Par exemple, si vous demandez une page Web, un seul paquet IP est souvent envoyé. Si une page Web plus grande est demandée,plusieurs paquets IP de réponse sont nécessaires pour transférer la page demandée.

Mise en cache

Les solutions d'équilibrage de charge de serveur de bas niveau telles que LVS atteignent leur limite si la mise en cache au niveau de l'application ou la prise en charge de la session d'application est requise. La mise en cache est un principe d'évolutivité important pour éviter des opérations coûteuses qui récupèrent les mêmes données à plusieurs reprises. Un cache est un magasin temporaire qui contient des données redondantes résultant d'une opération précédente de récupération de données. La valeur d'un cache dépend du coût de récupération des données par rapport au taux de réussite et à la taille de cache requise.

Sur la base de l'algorithme de planification de l'équilibreur de charge, les demandes d'une session utilisateur sont traitées par différents serveurs. Si un cache est utilisé côté serveur, les demandes parasites deviendront un problème. Une approche pour gérer cela consiste à placer le cache dans un espace global. memcached est une solution de cache distribuée populaire qui fournit un grand cache sur plusieurs machines. Il s'agit d'un cache distribué partitionné qui utilise un hachage cohérent pour déterminer le serveur de cache (démon) pour une entrée de cache donnée. En fonction du code de hachage de la clé de cache, la bibliothèque cliente mappe toujours le même code de hachage à la même adresse de serveur de cache. Cette adresse est ensuite utilisée pour stocker l'entrée du cache. La figure 3 illustre cette approche de mise en cache.

Le listing 2 utilise spymemcached, un memcachedclient écrit en Java, pour mettre en cache les HttpResponsemessages sur plusieurs machines. La spymemcachedbibliothèque implémente la logique client requise que je viens de décrire.

Listing 2. Cache HttpResponse basé sur Memcached