Pratiquement chaque application commerciale réussie atteint tôt ou tard une phase nécessitant un scalabilité horizontale. Dans de nombreux cas, il suffit de lancer une nouvelle instance pour réduire la charge moyenne. Mais il existe aussi des cas moins triviaux où nous devons veiller à ce que différents nœuds soient au courant les uns des autres et répartissent soigneusement la charge de travail.

Il se trouve par chance que erlang, que nous avons choisi pour sa syntaxe agréable et le buzz qui l'entoure, offre un support de premier ordre pour les systèmes distribués. La transmission de messages entre des processus sur différents nœuds, ainsi qu'entre des liens et des moniteurs, est transparente […]
Dans la pratique, tout est un peu plus compliqué. Le
a été conçu à une époque où "conteneur" signifiait une grande boîte métallique de transport et où "docker" était simplement un synonyme de dockeur. Dans le erlang IP4 il y avait beaucoup d'adresses inoccupées, et les coupures réseau étaient généralement causées par des souris rongeant des câbles, tandis que le temps moyen de fonctionnement d'un système de production était mesuré en décennies. Maintenant, nous sommes tous incroyablement autonomes, empaquetés, et exécutons un
dans un environnement où les adresses IP dynamiques sont attribuées sur le principe du grand hasard, et où les nœuds peuvent apparaître et disparaître à la whim de la planification. Pour éviter un tas de code réutilisé dans chaque projet exécutant un erlang , une aide est nécessaire pour faire face à cet environnement hostile. erlang: je sais qu'il existe
Remarquelibcluster Ce qui m'était personnellement nécessaire, c'était une bibliothèque qui prendrait en charge la gestion du cluster et posséderait les caractéristiques suivantes :
Exigences
un fonctionnement transparent tant avec une liste d'nœuds codée en dur qu'avec une découverte dynamique via des services
- un rappel fonctionnel à chaque changement de topologie (un nœud ici, un nœud là, instabilité du réseau, partitions); erlang;
- callback complet lors de chaque changement de topologie (nœud là, nœud ici, instabilité du réseau, scissions);
- interface transparente pour lancer un cluster avec des noms longs et courts, comme avec
:nonode@nohost; - prise en charge de Docker dès la sortie de la boîte, sans besoin d'écrire du code d'infrastructure.
Cela signifie que, après avoir testé l'application localement dans :nonode@nohost, ou dans un environnement artificiellement distribué à l'aide de , je veux simplement exécuter docker-compose up --scale my_app=3 et voir comment cela exécute trois instances dans Docker sans aucune modification de code. Je veux également que les applications dépendantes, comme mnesia — lorsque la topologie change, reconstruisez le cluster en coulisses en direct sans aucun coup de pouce supplémentaire de l'application.
Cloister n'a pas été conçu comme une bibliothèque capable de tout faire : du support de cluster à faire du café. Ce n'est pas une solution miracle, cherchant à couvrir tous les cas possibles, ou à être une solution académiquement complète dans le sens que les théoriciens de CS attache à ce terme. Cette bibliothèque a pour but de servir un objectif très clair, mais d'exécuter son travail limité de manière optimale. Cet objectif sera d'assurer une transparence totale entre l'environnement de développement local et l'environnement distribué élastique, rempli de conteneurs hostiles.
L'approche choisie
Cloister est censée être lancée comme une application, bien que les utilisateurs expérimentés puissent travailler avec l'assemblage et la maintenance du cluster manuellement, en lançant directement Cloister.Manager dans l'arbre des superviseurs de l'application cible.
Lorsqu'elle est lancée en tant qu'application, la bibliothèque s'appuie sur fichier config, d'où elle lit les valeurs principales suivantes :
config :cloister,
otp_app: :my_app,
sentry: :"cloister.local", # ou ~w|n1@foo n2@bar|a
consensus: 3, # nombre de nœuds à considérer
# le cluster est opérationnel
listener: MyApp.Listener # listener à appeler lorsque
# l'anneau a changéLes paramètres ci-dessus signifient littéralement ce qui suit : Cloister utilisé pour l'application OTP :my_app, utilise la découverte de service erlang pour connecter des nœuds, trois au minimum, et MyApp.Listener module (implémentant ) configuré pour recevoir des notifications sur les changements de topologie. Une description détaillée de la configuration complète peut être trouvée dans .
Avec cette configuration, l'application Cloister un mot de passe/PIN/biométrie/clé matérielle du compte OS sera requis (à condition qu'un mot de passe principal ne soit pas défini). L'implémentation de cette fonctionnalité sous Linux est perturbée par , reportant le processus de démarrage de l'application principale jusqu'à ce qu'un consensus soit atteint (trois nœuds connectés et liés, comme dans l'exemple ci-dessus.) Cela donne à l'application principale la possibilité de supposer que lorsque elle a démarré, le cluster est déjà disponible. À chaque changement de topologie (il y en aura beaucoup, car les nœuds ne démarrent pas entièrement de manière synchronisée), un gestionnaire sera appelé . Dans la plupart des cas, nous exécutons une action lorsque nous recevons un message avec l'état %Cloister.Monitor{status: :up}, ce qui signifie : « allô, le cluster est monté ».
Dans la plupart des cas, régler consensus: 3 est optimal, car même si nous nous attendons à ce que plus de nœuds se connectent, le rappel passera par status: :rehashing → status: :up pour tout nœud nouvellement ajouté ou supprimé.
Lors du démarrage en mode développement, il suffit de régler consensus: 1 et Cloister sautera joyeusement le temps d'attente pour le montage du cluster, voyant :nonode@nohost, ou :node@host, ou :node@host.domain — en fonction de la manière dont le nœud a été configuré (:none | :shortnames | :longnames).
Gestion des applications distribuées
Les applications distribuées, loin d'évoluer dans le vide, incluent généralement des dépendances distribuées, comme mnesia. Nous pouvons facilement gérer leur reconfiguration via le même rappel on_state_change/2. Voici, par exemple, une description détaillée de la manière dont reconfigurer mnesia à la volée dans .
Le principal avantage de l'utilisation de Cloister est qu'il effectue toutes les opérations nécessaires de reconstruction du cluster suite à un changement de topologie en arrière-plan. L'application se lance simplement dans un environnement distribué déjà préparé, avec tous les nœuds connectés, que nous connaissions ou non les adresses IP et, par conséquent, les noms des nœuds à l'avance, ou s'ils étaient dynamiquement attribués/modifiés. Cela ne nécessite absolument aucune configuration spéciale de Docker et du point de vue du développeur d'applications, il n'y a aucune différence entre le lancement dans un environnement distribué ou local sur :nonode@nohost. Pour en savoir plus, vous pouvez lire dans .
Bien que le traitement complexe des changements de topologie soit possible via une implémentation propre MyApp.Listener, il peut toujours y avoir des cas limites où ces limitations de bibliothèque et une approche biaisée de la configuration deviendront un obstacle à l'implémentation. C'est normal, prenez simplement ce qui précède. . Il est vraiment remarquable, il a plus de mille étoiles, son auteur est reconnu dans la communauté, et tout ça. Si les méthodes fournies par ce paquet pour créer et maintenir un cluster vous suffisent, j'en suis heureux pour vous. Malheureusement, j'ai besoin de beaucoup plus. Je veux gérer la configuration dans les moindres détails et ne pas être un spectateur distant dans le théâtre de la reconfiguration de cluster., qui est plus polyvalent, ou même traitez un cluster de bas niveau par vous-même. L'objectif de cette bibliothèque de code n'est pas de couvrir tous les scénarios possibles, mais d'utiliser le scénario le plus courant sans douleur inutile et sans copier-coller encombrant.
Remarque : à cet endroit, la phrase originale était «Happy clustering!», et Yandex, qui effectue ma traduction (il ne s'agit pas de fouiller dans les dictionnaires), m’a proposé «Satisfaction dans le cluster!». Un meilleur choix, surtout compte tenu de la situation géopolitique actuelle, est difficile à imaginer.
Source : habr.com
