Mise à l’échelle des microservices avec gRPC et Envoy Proxy – Partie 2
Dans la partie 1 de mon article de blog, j’ai parlé du style d’architecture des microservices, HTTP vs HTTP 2, des tampons de protocole et de gRPC. Dans ce blog, permettez-moi de partager sur l’équilibrage de charge et Envoy Proxy.
L’équilibrage de charge fait référence à la distribution efficace du trafic réseau entrant sur un groupe de serveurs principaux, également appelé batterie de serveurs ou pool de serveurs. Un équilibreur de charge remplit les fonctions suivantes:
L’équilibrage de charge peut être effectué par le client (équilibrage de charge côté client) comme Netflix Ribbon ou vous pouvez avoir un serveur dédié qui équilibre la charge des demandes (équilibrage de charge serveur / proxy) comme Nginx, HAProxy, Consul, DNS et Envoy Procuration. Chacune de ces méthodes a ses avantages et ses inconvénients, comme indiqué dans le tableau ci-dessous.
Comparaison de l’équilibrage de charge côté proxy et côté client
En raison des inconvénients de l’équilibrage de charge côté client, la plupart des systèmes construits à l’aide d’une architecture de microservices utilisent l’équilibrage de charge proxy.
Pour l’un des clients pour lesquels je travaillais, Consul était largement utilisé comme équilibreur de charge et à ce moment-là (vers l’année 2018), Envoy Proxy était toujours en cours d’évaluation. Par conséquent, nous avions procédé avec Consul en tant qu’équilibreur de charge pour un système que nous construisions.
Mais au fur et à mesure que notre système a commencé à évoluer, c’est-à-dire que nous avons commencé à avoir plus de clients et à son tour un débit plus élevé, nous avons commencé à observer une dégradation des performances sur quelques serveurs. Peu de serveurs recevaient plus de débit que les autres et avaient donc des temps de réponse plus élevés. Après une enquête plus approfondie, nous avons identifié que le problème résidait dans l’équilibreur de charge Consul, la cause principale étant le multiplexage HTTP2. L’équilibreur de charge Consul a été conçu pour l’équilibrage de charge basé sur HTTP et ne prend pas en charge l’équilibrage de charge basé sur HTTP2 à l’époque.
Considérez une connexion unique d’un client au serveur Consul, comme indiqué dans la figure ci-dessous, avec 5 demandes multiplexées sur la même connexion. Consul, conçu pour l’équilibrage de charge basé sur HTTP, considère qu’un client créerait une nouvelle connexion HTTP pour chaque demande. Et pour chacune de ces connexions entrantes, Consul crée une connexion HTTP sortante correspondante vers un serveur principal. Donc, dans ce cas, même s’il y a 5 demandes, Consul la considère comme une seule demande car elles sont toutes multiplexées sur une seule connexion et les transmet au même serveur principal. Mais votre serveur principal devrait désormais traiter 5 demandes au lieu de 1.
Envoy résout ce problème avec sa prise en charge de l’équilibrage de charge basé sur HTTP2.
Prenons un exemple similaire à celui ci-dessus, où vous avez une seule connexion d’un client au serveur proxy Envoy, comme illustré dans la figure ci-dessous, avec 5 demandes multiplexées sur la même connexion. Contrairement à Consul, Envoy reconnaît les 5 demandes multiplexées et équilibre la charge de chaque demande en créant 5 connexions HTTP2 individuelles vers 5 serveurs principaux différents.
Envoy Proxy est un proxy L7 et un bus de communication conçu pour les grandes architectures modernes orientées services.
Les équilibreurs de charge de la couche 7 fonctionnent au plus haut niveau du modèle OSI, la couche Application (sur Internet, HTTP est le protocole dominant à cette couche). Les équilibreurs de charge de la couche 7 basent leurs décisions de routage sur diverses caractéristiques de l’en-tête HTTP et sur le contenu réel du message, comme l’URL, le type de données (texte, vidéo, graphiques) ou les informations contenues dans un cookie.
La configuration du proxy Envoy se compose principalement d’écouteurs, de filtres et de clusters.
Les auditeurs
Un écouteur est un emplacement réseau nommé (par exemple, port, socket de domaine Unix, etc.) qui indique à Envoy l’emplacement réseau sur lequel il doit écouter et auquel les clients en aval peuvent se connecter. Envoy expose un ou plusieurs écouteurs auxquels les hôtes en aval se connectent, comme illustré dans la figure ci-dessous.
Filtres
Un ensemble de filtres fournis indique à Envoy comment il doit traiter les messages qu’il entend. Envoy prend en charge les filtres d’écoute, les filtres réseau (L3 / L4) et les filtres HTTP.
Filtres d’écoute sont traités avant les filtres de niveau réseau et ont la possibilité de manipuler les métadonnées de connexion, généralement pour influencer la façon dont la connexion est traitée par des filtres ou des clusters ultérieurs.
Filtres réseau (L3 / L4) forment le cœur de la gestion des connexions Envoy. Il existe trois types de filtres réseau:
Filtres HTTP peut être écrit pour fonctionner sur des messages de niveau HTTP sans connaître le protocole physique sous-jacent (HTTP / 1.1, HTTP / 2, etc.) ou les capacités de multiplexage.
Clusters
Un cluster indique à Envoy un ou plusieurs hôtes en amont logiquement similaires, auxquels Envoy peut envoyer des requêtes entrantes par proxy. Envoy découvre les membres d’un cluster via la découverte de services. Il détermine éventuellement l’intégrité des membres du cluster via une vérification active de l’intégrité. Le membre de cluster vers lequel Envoy achemine une demande est déterminé par la stratégie d’équilibrage de charge.
Envoy prend en charge les politiques d’équilibrage de charge suivantes:
Tourniquet pondéré
Chaque hôte en amont disponible est sélectionné dans un tour de rôle. Si des pondérations sont attribuées aux points d’extrémité dans une localité, un calendrier de tourniquet pondéré est utilisé, où des points d’extrémité plus pondérés apparaissent plus souvent dans la rotation pour atteindre la pondération effective.
Moindre demande pondérée
L’équilibreur de charge le moins sollicité utilise différents algorithmes selon que les hôtes ont des poids identiques ou différents.
Tous les poids sont égaux
Un algorithme O (1) qui sélectionne N hôtes disponibles aléatoires comme spécifié dans la configuration (2 par défaut) et sélectionne l’hôte qui a le moins de requêtes actives.
Tous les poids ne sont pas égaux
Si deux hôtes ou plus dans le cluster ont des poids d’équilibrage de charge différents, l’équilibreur de charge passe dans un mode où il utilise un programme de répétition alternée pondéré dans lequel les poids sont ajustés dynamiquement en fonction de la charge de demande de l’hôte au moment de la sélection (le poids est divisé par le nombre de demandes actuellement actives)
Ring Hash
L’équilibreur de charge de hachage en anneau / modulo implémente un hachage cohérent vers les hôtes en amont. Chaque hôte est mappé sur un cercle («l’anneau») en hachant son adresse; chaque demande est ensuite acheminée vers un hôte en hachant une propriété de la demande et en trouvant l’hôte correspondant le plus proche dans le sens des aiguilles d’une montre autour de l’anneau. Cette technique est également connue sous le nom de hachage «Ketama» et, comme tous les équilibreurs de charge basés sur le hachage, elle n’est efficace que lorsque le routage de protocole est utilisé qui spécifie une valeur à hacher.
Maglev
L’équilibreur de charge Maglev implémente un hachage cohérent vers les hôtes en amont. L’idée est de générer une table de recherche de taille fixe (65537), chaque backend prenant des entrées dans la table. Ces méthodes fournissent deux propriétés souhaitables dont Maglev a également besoin pour une sélection de backend résiliente:
– Équilibrage de charge: chaque backend recevra un nombre presque égal de connexions.
– Perturbation minimale: lorsque l’ensemble des backends change, une connexion sera probablement envoyée au même backend qu’auparavant.
Maglev peut être utilisé en remplacement de l’équilibreur de charge de hachage annulaire à tout endroit où un hachage cohérent est souhaité. Comme l’équilibreur de charge de hachage en anneau, un équilibreur de charge de hachage cohérent n’est efficace que lorsque le routage de protocole est utilisé qui spécifie une valeur à hacher.
Aléatoire
L’équilibreur de charge aléatoire sélectionne un hôte disponible aléatoire. L’équilibreur de charge aléatoire fonctionne généralement mieux que le tourniquet si aucune stratégie de vérification de l’intégrité n’est configurée. La sélection aléatoire évite les biais vers l’hôte dans l’ensemble qui vient après un hôte défaillant.
Après avoir résolu le problème d’équilibrage de charge avec Envoy, nous avons été confrontés à un autre problème commercial, dont la solution signifiait un débit de lecture plus important (~ 30k) pour le système que nous avions construit précédemment. Le système devait recevoir une demande à chaque lancement d’application, c’est-à-dire de la page d’accueil.
Pour éviter de rencontrer des problèmes similaires avec les temps de réponse comme auparavant, nous avons décidé de déployer un cluster dédié en lecture seule pour le débit de lecture supplémentaire que ce système devait recevoir. Nous avons introduit un en-tête de demande pour différencier les demandes faites depuis la page d’accueil. Cependant, le routage de ces demandes vers le cluster en lecture seule n’a nécessité que deux modifications sur Envoy.
Mais nous ne voulions pas acheminer tout le trafic de la page d’accueil vers le cluster en lecture seule à la fois. Au lieu de cela, nous voulions un déploiement incrémentiel. Envoy Proxy nous a aidés à résoudre ce problème avec facilité grâce à sa pondération de cluster, comme mentionné ci-dessus dans les politiques d’équilibrage de charge.
Comme indiqué dans la configuration ci-dessous, nous avons commencé par acheminer 5% du trafic de la page d’accueil vers le cluster en lecture seule, en l’augmentant progressivement jusqu’à ce que nous ayons acheminé tous les 100% du trafic vers le cluster en lecture seule.
gRPC, construit sur HTTP / 2, nous fournit un protocole de communication à haute vitesse qui peut tirer parti du streaming bidirectionnel, du multiplexage et plus encore. Protocol Buffer fournit des implémentations de bibliothèques client / serveur dans de nombreuses langues. Il a un format binaire et, par conséquent, fournit une empreinte beaucoup plus petite que les charges utiles JSON / XML. Lorsque vous visez le moins de temps de réponse, optez pour gRPC comme protocole de communication.
Envoy Proxy est un proxy L7 et un bus de communication conçu pour les grandes architectures modernes orientées services. Il prend en charge l’équilibrage de charge des requêtes HTTP et gRPC. Envoy fournit un riche ensemble de fonctionnalités via les filtres intégrés que l’on peut rapidement exploiter via la configuration du récepteur. Le paradigme de la chaîne de filtres est un mécanisme puissant et Envoy permet aux utilisateurs d’implémenter leurs propres filtres en étendant son API.