Téměř každá úspěšná business aplikace se dříve či později dostane do fáze, kdy je potřeba horizontální škálování. V mnoha případech stačí spustit novou instanci a snížit průměrné zatížení. Existují však i méně triviální situace, kdy musíme zajistit, aby různé uzly věděly o sobě navzájem a správně rozdělovaly pracovní zátěž.

Tak šťastně se sešlo, že erlang, který jsme si vybrali pro jeho příjemnou syntaxi a humbuk kolem, má špičkovou . V teorii to zní zcela triviálně:
Přenášení zpráv mezi procesy na různých uzlech, stejně jako mezi odkazy a monitory je transparentní […]
Ve skutečnosti je vše o něco složitější. Distribuovaný erlang byl vyvinut, když "kontejner" znamenal velkou železnou krabici k přepravě a "docker" byl pouhým synonymem přístavního manipulanta. V IP4 bylo mnoho neobsazených adres, na síťových výpadcích obvykle měli na svědomí krysí, které prokousaly kabely, a průměrná doba provozuschopnosti výrobního systému se měřila v desetiletích.
Nyní jsme všichni nesmírně soběstační, zabalení a spouštíme distribuovaný erlang v prostředí, kde se dynamické IP adresy přidělují na základě velké náhody a uzly se mohou objevovat a mizet podle libovůle levé nohy plánovače. Abychom se vyhnuli hromadě šablonového kódu v každém projektu spouštějícím distribuovaný erlang, je potřeba pomoc.
Poznámka: Vím, že existuje . Opravu skvělé, má více než tisíc hvězdiček, autor je známý v komunitě a všechno takové. Pokud vám vyhovuje nabízené způsoby vytváření a správy klastru tímto balíčkem – jsem šťastný za vás. Mně, bohužel, je potřeba mnohem víc. Chci mít detailní kontrolu nad konfigurací a být aktivním účastníkem v divadle přeorganizace klastra.
Požadavky
Co jsem potřeboval osobně, byla knihovna, která se postará o správu klastru a bude mít následující vlastnosti:
- transparentní práce jak s pevně zakódovaným seznamem uzlů, tak s dynamickým objevováním přes služby erlang;
- plnohodnotný callback při každé změně topologie (uzel tam, uzel sem, nestabilita sítě, rozdělení);
- transparentní rozhraní pro spuštění clusteru s dlouhými a krátkými názvy, stejně jako s
:nonode@nohost; - podporou Dockeru přímo z krabice, bez nutnosti psát infrastrukturní kód.
To znamená, že poté, co jsem aplikaci otestoval lokálně v :nonode@nohost, nebo v uměle rozděleném prostředí pomocí , chci jednoduše spustit docker-compose up --scale my_app=3 a vidět, jak fungují tři instance v Dockerech bez jakýchkoli změn kódu. Také chci, aby závislé aplikace, například mnesia — když se topologie mění, měly možnost přeorganizovat cluster naživo bez jakéhokoli dalšího podnětu od aplikace.
Cloister nebyl navržen jako knihovna, která by uměla všechno: od podpory clusteru po přípravu kávy. Není to stříbrná kulka snažící se pokrýt všechny možné případy nebo být akademicky úplným řešením ve smyslu, který teoretici od CS vkládají do tohoto termínu. Tato knihovna má sloužit velmi konkrétnímu cíli, ale vykonávat svůj ne příliš velký objem práce dokonale. Tento cíl bude spočívat v zajištění úplné transparentnosti mezi místním vývojovým prostředím a rozděleným elastickým prostředím, plným nepřátelských kontejnerů.
Zvolený přístup
Cloister předpokládá spuštění jako aplikace, ačkoli zkušení uživatelé mohou pracovat se stavbou a údržbou clusteru ručně, přímo spuštěním Cloister.Manager v hierarchii supervizorů cílové aplikace.
Při spuštění jako aplikace, knihovna se spoléhá na config, odkud vyčítá následující základní hodnoty:
config :cloister,
otp_app: :my_app,
sentry: :"cloister.local", # nebo ~w|n1@foo n2@bar|a
consensus: 3, # počet uzlů, které je třeba považovat
# cluster je již spuštěn
listener: MyApp.Listener # posluchač, který bude zavolán, když
# kruh se změnilParametry výše znamenají doslovně následující: Cloister používá se pro OTP aplikaci :my_app, používá erlang service discovery k připojení uzlů, alespoň tří, a MyApp.Listener modul (implementující ) je nastaven tak, aby dostával oznámení o změnách topologie. Podrobné informace o celé konfiguraci lze nalézt .
Při takové konfiguraci se aplikace Cloister bude , odkládající proces spuštění hlavní aplikace do doby dosažení konsenzu (tři uzly jsou připojeny a spojeny, jak je uvedeno výše). To umožňuje hlavní aplikaci předpokládat, že když se spustí, cluster je již dostupný. Při každé změně topologie (těch bude mnoho, protože uzly se spouští ne zcela synchronně) bude vyvolán obslužný program . Ve většině případů provádíme akci, když obdržíme zprávu o stavu %Cloister.Monitor{status: :up}, což znamená: „ahoj, cluster je sestaven“.
Ve většině případů je nastavení consensus: 3 optimální, protože i když očekáváme, že se připojí více uzlů, zpětné volání projde status: :rehashing → status: :up pro každý nový přidaný nebo odstraněný uzel.
Při spuštění v režimu vývoje stačí jednoduše nastavit consensus: 1 a Cloister rádoby rychle přejde čekání na sestavení clusteru, když uvidí :nonode@nohost, nebo :node@host, nebo :node@host.domain — v závislosti na tom, jak byl uzel nastaven (:none | :shortnames | :longnames).
Správa distribuovaných aplikací
Distribuované aplikace běžně neexistují v izolaci a obvykle zahrnují také distribuované závislosti, jako jsou mnesia. Je pro nás snadné zpracovat jejich překonfiguraci ze stejného zpětného volání on_state_change/2. Například zde je podrobný popis toho, jak přenastavit mnesia za běhu v .
Hlavní výhodou použití Cloister je to, že provádí všechny potřebné operace k rekonstrukci clusteru po změně topologie pod kapotou. Aplikace se jednoduše spouští v již připraveném distribuovaném prostředí, se všemi připojenými uzly, nezávisle na tom, zda známe IP adresy a tím pádem i názvy uzlů předem, nebo byly dynamicky přiděleny/změněny. To nevyžaduje žádná zvláštní nastavení konfigurace Dockeru a z hlediska vývojáře aplikací není žádný rozdíl mezi spuštěním v distribuovaném prostředí nebo místně na :nonode@nohost. Více o tom si můžete přečíst v .
I když je složité zpracování změn topologie možné prostřednictvím vlastního provedení MyApp.Listener, vždy mohou být hraniční případy, kdy tyto omezení knihovny a zaujatý přístup k konfiguraci mohou být kamenem úrazu při implementaci. Je to v pořádku, jednoduše vezměte výše uvedené libcluster, který je všestrannější, nebo dokonce zpracovat nízkoúrovňový cluster sami. Cílem této knihovny kódu není pokrýt všechny možné scénáře, ale využít nejběžnější scénář bez zbytečné bolesti a nepraktických kopírování a vkládání.
Poznámka: na tomto místě v originále byla fráze „Happy clustering!“, a Yandex, kterým překládám (nebudu přece procházet slovníky), mi navrhl variantu „Šťastné shlukování!“. Lepší překlad, zejména s ohledem na současnou geopolitickou situaci, snad ani není možné si představit.
Zdroj: habr.com
