26. februar hadde vi meet-up om Apache Ignite GreenSource, hvor bidragsytere fra open source-prosjektet talte. . Et viktig arrangement for dette fellesskapet var ombyggingen av komponenten , som lar deg rulle ut brukertilpassede mikrotjenester direkte i Ignite-klyngen. Om denne krevende prosessen snakket , programvareingeniÞr og bidragsyter til Apache Ignite i over to Är.

La oss begynne med hva Apache Ignite egentlig er. Dette er en database som fungerer som et distribuert nĂžkkel/verdi-lager med stĂžtte for SQL, transaksjoner og caching. I tillegg lar Ignite deg rulle ut tilpassede tjenester direkte i Ignite-klyngen. Utviklere fĂ„r tilgang til alle verktĂžyene som Ignite tilbyr â distribuerte datastrukturer, Messaging, Streaming, Compute og Data Grid. For eksempel, ved bruk av Data Grid forsvinner problemet med administrering av en separat infrastruktur for datalagring og de pĂ„fĂžlgende kostnadene som fĂžlger med det.

Ved Ă„ bruke API Service Grid kan du distribuere en tjeneste ved enkelt Ă„ spesifisere distribusjonsskjemaet i konfigurasjonen samt selve tjenesten.
Normalt er distribusjonsskjemaet en indikasjon pÄ hvor mange instanser som skal distribueres pÄ klyngeknutene. Det finnes to typiske distribusjonsskjemaer. Den fÞrste er Cluster Singleton: til enhver tid vil det garantert vÊre én instans av brukertjenesten tilgjengelig i klyngen. Den andre er Node Singleton: pÄ hver knute i klyngen er det rullet ut én instans av tjenesten.

Brukeren kan ogsÄ spesifisere antallet instanser av tjenesten i hele klyngen og definere et predikat for Ä filtrere relevante noder. I et slikt scenario vil Service Grid selv beregne optimal distribusjon for distribusjon av tjenester.
I tillegg finnes det en funksjon som heter Affinity Service. Affinity er en funksjon som definerer forholdet mellom nÞkler og partisjoner, samt forholdet mellom partisjoner og noder i topologien. Gjennom nÞkkelen kan man bestemme primary-node der dataene lagres. PÄ denne mÄten kan du assosiere din egen tjeneste med nÞkkelen og cache-funksjonen. Ved endring av cache-funksjonen vil det skje en automatisk redesployering. Slik vil tjenesten alltid bli plassert nÊr dataene den skal manipulere, og dermed redusere kostnadene ved tilgang til informasjon. Dette kan kalles en form for kolokalisert databehandling.
NÄ som vi har gÄtt gjennom hva som er flott med Service Grid, vil vi fortelle om dens utviklingshistorie.
Hva var tidligere
Den forrige implementeringen av Service Grid var basert pÄ et transaksjonsreplikerende systemcache kalt Ignite. Med ordet "cache" i Ignite refereres det til et lagringsystem. Det er altsÄ ikke noe midlertidig, som man kanskje ville tro. Selv om cachen er replikert og hver node inneholder hele datasettet, har cachen en partisjonert fremstilling. Dette er relatert til optimalisering av lagring.

Hva skjedde nÄr en bruker Þnsket Ä deployere en tjeneste?
- Alle nodene i klyngen abonnerte pÄ dataoppdateringer i lagringen gjennom den innebygde mekanismen Continuous Query.
- Initieringsnoden lagde en inngang i databasen under en read-committed transaksjon, som inneholdt konfigurasjonen av tjenesten, inkludert den serialiserte instansen.
- NÄr koordinatoren mottok varselet om den nye posten, beregnet han distribusjonen basert pÄ konfigurasjonen. Den mottatte objektet ble lagret tilbake i databasen.
- Hvis noden var med i distribusjonen, mÄtte koordinatoren deployere den.
Hva var vi misfornĂžyde med
PÄ et tidspunkt kom vi til den konklusjon at man ikke kan jobbe med tjenester pÄ denne mÄten. Det var flere grunner til dette.
Hvis det oppsto en feil under deployeringen, kunne man bare fĂ„ vite om den fra loggene til den noden der alt skjedde. Det eksisterte bare asynkron deployering, sĂ„ etter at brukeren fikk tilbake kontrollen fra deploy-metoden, var det nĂždvendig med ekstra tid for Ă„ starte tjenesten â og i lĂžpet av denne tiden kunne ikke brukeren administrere noe. For Ă„ utvikle Service Grid videre, implementere nye funksjoner, tiltrekke nye brukere og gjĂžre livet enklere for alle, mĂ„tte vi endre pĂ„ noe.
NÄr vi designet det nye Service Grid, Þnsket vi fÞrst og fremst Ä gi en garanti for synkron distribusjon: sÄ snart brukeren fÄr kontroll tilbake fra API, kan de umiddelbart bruke tjenestene. Vi Þnsket ogsÄ Ä gi initiatoren muligheten til Ä hÄndtere distribusjonsfeil.
Videre Þnsket vi Ä lette implementeringen, spesielt Ä unngÄ transaksjoner og rebalansering. Selv om cache er replikert og det ikke er rebalansering, oppstod det problemer under stÞrre distribusjoner med flere noder. NÄr topologien endres, mÄ nodene utveksle informasjon, og under en stor distribusjon kan disse dataene veie mye.
NÄr topologien var ustabil, mÄtte koordinatoren beregne distribusjonen av tjenester pÄ nytt. Generelt kan arbeidet med transaksjoner pÄ en ustabil topologi fÞre til vanskeligforutsigbare feil.
Problemer
Hvilke globale endringer kommer uten samtidige problemer? Det fÞrste av dem var endringen av topologi. Man mÄ forstÄ at nÄr som helst, selv i lÞpet av distribusjonen av tjenesten, kan en node bli med i eller forlate klyngen. Mer enn det, hvis en node blir med i klyngen under distribusjonen, mÄ all informasjon om tjenestene overfÞres konsekvent til den nye noden. Og dette gjelder ikke bare det som allerede er distribuert, men ogsÄ nÄvÊrende og fremtidige distribusjoner.
Dette er bare ett av problemene som kan samles i en egen liste:
- Hvordan distribuere statisk konfigurerte tjenester ved oppstart av noden?
- Hva skal man gjĂžre nĂ„r noden forlater klyngen â hvis noden hadde vert tjenester?
- Hva skal man gjĂžre hvis koordinatoren har endret seg?
- Hva skal man gjĂžre hvis klienten er reconnected til klyngen?
- MÄ vi hÄndtere forespÞrslene for aktivering/deaktivering, og hvordan?
- Hva hvis cache destruksjonen ble kalt, men vi har tjenester som er avhengige av den?
Og dette er langt ifra alt.
Solution
Som mĂ„l valgte vi en Event Driven tilnĂŠrming med implementering av prosesskommunikasjon ved hjelp av meldinger. I Ignite er allerede to komponenter implementert, som lar noder sende meldinger til hverandre â communication-spi og discovery-spi.

Communication-spi gjÞr det mulig for noder Ä kommunisere direkte og sende meldinger. Det er godt egnet for Ä overfÞre store datamengder. Discovery-spi gjÞr det mulig Ä sende en melding til alle noder i klyngen. I den standard implementeringen gjÞres dette ved hjelp av en "ring"-topologi. Det finnes ogsÄ integrasjon med Zookeeper; i sÄ fall brukes en "stjerne"-topologi. Det er ogsÄ viktig Ä merke seg at discovery-spi gir garantier for at meldingen nÞyaktig vil bli levert i riktig rekkefÞlge til alle noder.
La oss se pÄ deploy-protokollen. Alle brukerforespÞrselene om deploy og undeploy sendes via discovery-spi. Dette gir fÞlgende garantier:
- ForespÞrselen vil bli mottatt av alle nodene i klyngen. Dette vil tillate videre behandling av forespÞrselen ved endring av koordinator. Det betyr ogsÄ at hver node vil ha alle nÞdvendige metadata for én melding, som tjenestekonfigurasjon og dens serialiserte instans.
- Den strenge rekkefÞlgen pÄ leveringen av meldinger gjÞr det mulig Ä lÞse konflikter mellom konfigurasjoner og konkurrerende forespÞrsel.
- Siden en nodes inntreden i topologien ogsÄ behandles via discovery-spi, vil den nye noden motta all nÞdvendig informasjon for Ä arbeide med tjenestene.
NÄr en forespÞrsel mottas, validerer nodene i klyngen den og danner oppgaver for behandling. Disse oppgavene legges i en kÞ og prosesseres deretter i en annen trÄd av en egen worker. Dette er implementert pÄ denne mÄten fordi deploy kan ta betydelig tid, og det er uakseptabelt Ä forsinke den dyre discovery-strÞmmen.
Alle forespĂžrslene fra kĂžen behandles av deployement-manageren. Den har en spesifikk worker som henter oppgaven fra denne kĂžen og initialiserer den for Ă„ starte distribusjonen. Etter dette skjer fĂžlgende:
- Hver node beregner selv fordelingen takket vĂŠre den nye deterministiske tildelingsfunksjonen.
- Nodene danner en melding med resultatene av deployen og sender den til koordinatoren.
- Koordinatoren aggregerer alle meldingene og danner resultatet av hele deploy-prosessen, som sendes via discovery-spi til alle nodene i klyngen.
- NÄr resultatet mottas, avsluttes deploy-prosessen, hvoretter oppgaven fjernes fra kÞen.

Ny hendelsesdrevet design: org.apache.ignite.internal.processors.service.IgniteServiceProcessor.java
Hvis det oppstod en feil under distribusjonen, vil noden straks inkludere denne feilen i meldingen som sendes til koordinatoren. Etter aggregasjonen av meldingene vil koordinatoren ha informasjon om alle feilene under distribusjonen og sende denne meldingen via discovery-spi. Feilinformasjonen vil vÊre tilgjengelig pÄ hvilken som helst node i klyngen.
Alle viktige hendelser i Service Grid behandles i henhold til denne arbeidsalgoritmen. For eksempel er endring av topologi ogsÄ en melding via discovery-spi. Generelt, sammenlignet med hva som var, har protokollen blitt ganske lettvektig og pÄlitelig. SÄ mye at den kan hÄndtere enhver situasjon under distribusjonen.
Hva skjer videre
NĂ„ om planene. Enhver stĂžrre oppdatering i Ignite-prosjektet utfĂžres som en initiativ for forbedring av Ignite, kjent som IEP. Redesignen av Service Grid har ogsĂ„ et IEP â med det morsomme navnet «Bytte av olje i Service Grid». Men i realiteten byttet vi ikke olje i motoren, men hele motoren.
Oppgavene i IEP er delt opp i 2 faser. Den fĂžrste fasen er en stor fase som innebĂŠrer omarbeiding av distribusjonsprotokollen. Den er allerede integrert i masteren, og du kan prĂžve det nye Service Grid som vil vĂŠre tilgjengelig i versjon 2.8. Den andre fasen inkluderer mange andre oppgaver:
- Hot redeploy
- Versjonering av tjenester
- Ăkt feilresistens
- Tynn klient
- VerktÞy for overvÄkning og mÄling av ulike metrikker
Til slutt kan vi anbefale Service Grid for bygging av feiltolerante systemer med hÞy tilgjengelighet. Vi inviterer deg ogsÄ til Ä bli med oss i og for Ä dele erfaringene dine. Din erfaring er virkelig viktig for fellesskapet; den vil hjelpe med Ä forstÄ hva vi skal gjÞre videre og hvordan vi skal utvikle komponenten i fremtiden.
Kilde: habr.com
