Nesten hver vellykket forretningsapplikasjon går før eller siden inn i en fase der horisontal skalering er nødvendig. I mange tilfeller kan du ganske enkelt starte en ny instans og redusere belastningsgjennomsnittet. Men det er også mindre trivielle tilfeller der vi må sørge for at ulike noder vet om hverandre og fordeler arbeidsmengden nøye.
Det viste seg så heldig at erlang, som vi valgte for sin hyggelige syntaks og hype rundt den, har en førsteklasses
Meldingsoverføring mellom prosesser på forskjellige noder, så vel som mellom lenker og monitorer, er gjennomsiktig […]
I praksis er alt litt mer komplisert. Distribuert erlang ble utviklet da "container" betydde en stor jernkasse for frakt, og "docker" var ganske enkelt et synonym for longshoreman. I IP4 det var mange ledige adresser, nettverksbrudd var vanligvis forårsaket av rotter som tygget gjennom kabelen, og den gjennomsnittlige oppetiden til produksjonssystemet ble målt i flere tiår.
Nå er vi alle utrolig selvforsynt, pakket og kjører distribuert erlang i et miljø hvor dynamiske IP-adresser deles ut etter prinsippet om stor tilfeldighet, og noder kan dukke opp og forsvinne etter innfall av venstre hæl på planleggeren. For å unngå haugevis av standardkode i hvert prosjekt som kjører en distribuert erlang, for å bekjempe det fiendtlige miljøet, er det nødvendig med hjelp.
Note: Jeg er klar over at det er libcluster
Krav
Det jeg personlig trengte var et bibliotek som ville overta administrasjonen av klyngen og ville ha følgende egenskaper:
- transparent arbeid med både en hardkodet liste over noder og dynamisk oppdagelse gjennom tjenester erlang;
- fullt funksjonell tilbakeringing for hver topologiendring (node der, node her, nettverksustabilitet, splittelser);
- gjennomsiktig grensesnitt for å lansere en klynge med lange og korte navn, som med
:nonode@nohost
; - Docker-støtte ut av esken, uten å måtte skrive infrastrukturkode.
Det siste betyr at etter at jeg testet applikasjonen lokalt i :nonode@nohost
, eller i et kunstig distribuert miljø ved hjelp av test_cluster_task
docker-compose up --scale my_app=3
og se hvordan den kjører tre forekomster i docker uten noen kodeendringer. Jeg vil også ha avhengige applikasjoner som mnesia
- når topologien endres, bak kulissene bygger de om klyngen live uten noe ekstra kick fra applikasjonen.
Kloster var ikke ment å være et bibliotek med alt fra å støtte en klynge til å lage kaffe. Det er ikke en sølvkule som har som mål å dekke alle mulige saker, eller være en faglig komplett løsning i den forstand at teoretikere fra CS lagt inn i dette begrepet. Dette biblioteket er designet for å tjene et veldig klart formål, men gjør den ikke altfor store jobben perfekt. Dette målet vil være å gi fullstendig åpenhet mellom det lokale utviklingsmiljøet og et distribuert elastisk miljø fullt av fiendtlige containere.
Valgt tilnærming
Kloster er ment å kjøres som en applikasjon, selv om avanserte brukere kan arbeide med montering og vedlikehold av klyngen manuelt ved å kjøre direkte Cloister.Manager
i målapplikasjonens veiledertre.
Når det kjøres som en applikasjon, er biblioteket avhengig av config
, hvorfra den leser følgende grunnleggende verdier:
config :cloister,
otp_app: :my_app,
sentry: :"cloister.local", # or ~w|n1@foo n2@bar|a
consensus: 3, # number of nodes to consider
# the cluster is up
listener: MyApp.Listener # listener to be called when
# the ring has changed
Parametrene ovenfor betyr bokstavelig talt følgende: Kloster brukes til OTP-applikasjon :my_app
, bruker erlang service discovery for å koble sammen noder, minst tre, og MyApp.Listener
modul (implementering @behaviour Cloister.Listener
Med denne konfigurasjonen vil applikasjonen Kloster vil MyApp.Listener.on_state_change/2
%Cloister.Monitor{status: :up}
, som betyr: "Hei, klyngen er satt sammen."
I de fleste tilfeller, installasjon consensus: 3
er optimal fordi selv om vi forventer at flere noder kobles til, vil tilbakeringingen gå gjennom status: :rehashing
→ status: :up
på enhver ny lagt til eller fjernet node.
Når du starter i utviklingsmodus, trenger du bare å stille inn consensus: 1
и Kloster vil gjerne hoppe over ventetiden på klyngemontering når han ser :nonode@nohost
Eller :node@host
Eller :[email protected]
- avhengig av hvordan noden ble konfigurert (:none | :shortnames | :longnames
).
Distribuert applikasjonsadministrasjon
Distribuerte applikasjoner som ikke er i et vakuum inkluderer vanligvis distribuerte avhengigheter, som f.eks mnesia
. Det er enkelt for oss å håndtere rekonfigureringen deres fra samme tilbakeringing on_state_change/2
. Her er for eksempel en detaljert beskrivelse av hvordan du rekonfigurerer mnesia
på fly inn
Den største fordelen med å bruke Kloster er at den utfører alle nødvendige operasjoner for å gjenoppbygge klyngen etter en topologiendring under panseret. Applikasjonen kjører ganske enkelt i et allerede forberedt distribuert miljø, med alle noder tilkoblet, uavhengig av om vi kjenner IP-adressene og dermed nodenavnene på forhånd, eller de er dynamisk tildelt/endret. Dette krever absolutt ingen spesielle docker-konfigurasjonsinnstillinger, og fra en applikasjonsutviklers synspunkt er det ingen forskjell mellom å kjøre i et distribuert miljø eller å kjøre i et lokalt. :nonode@nohost
. Du kan lese mer om dette i
Selv om kompleks håndtering av topologiendringer er mulig gjennom en tilpasset implementering MyApp.Listener
, kan det alltid være edge-tilfeller der disse bibliotekbegrensningene og konfigurasjonsskjevhetene viser seg å være hjørnesteinene i implementeringen. Det er ok, bare ta ovenstående libcluster
, som er mer generell, eller til og med håndtere lavnivåklyngen selv. Målet med dette kodebiblioteket er ikke å dekke alle mulige scenarioer, men å bruke det vanligste scenariet uten unødvendig smerte og tungvint copy-paste.
Merk: på dette tidspunktet i originalen var det uttrykket "Happy clustering!", og Yandex, som jeg oversetter med (jeg trenger ikke å gå gjennom ordbøker selv), tilbød meg alternativet "Happy clustering!" Det er kanskje umulig å tenke seg en bedre oversettelse, spesielt i lys av dagens geopolitiske situasjon.
Kilde: www.habr.com