Den 26 februari höll vi meeten Apache Ignite GreenSource, dÀr bidragsgivare frÄn open source-projektet deltog. . En viktig hÀndelse i detta samhÀlles liv var omstruktureringen av komponenten , som gör det möjligt att distribuera anvÀndarspecifika mikrotjÀnster direkt i Ignite-klustret. Om denna komplexa process berÀttade , mjukvaruingenjör och bidragsgivare till Apache Ignite i mer Àn tvÄ Är.

LĂ„t oss börja med vad Apache Ignite egentligen Ă€r. Det Ă€r en databas som utgör ett distribuerat Key/Value-lager med stöd för SQL, transaktioner och caching. Dessutom gör Ignite det möjligt att distribuera anvĂ€ndarspecifika tjĂ€nster direkt i Ignite-klustret. Utvecklare fĂ„r tillgĂ„ng till alla verktyg som Ignite erbjuder â distribuerade datatyper, Messaging, Streaming, Compute och Data Grid. Till exempel, vid anvĂ€ndning av Data Grid försvinner problemet med att administrera en separat infrastruktur för datalagring och följaktligen de kostnader som följer med detta.

Genom att anvÀnda API:et för Service Grid kan du distribuera en tjÀnst genom att enkelt ange distributionsschemat i konfigurationen och dÀrmed sjÀlva tjÀnsten.
Vanligtvis Àr distributionsschemat en angivelse av antalet instanser som ska distribueras pÄ klustrets noder. Det finns tvÄ typiska distributionsscheman. Det första Àr Cluster Singleton: vid varje given tidpunkt kommer en instans av den anvÀndarspecifika tjÀnsten garanteras vara tillgÀnglig i klustret. Det andra Àr Node Singleton: varje nod i klustret har en instans av tjÀnsten distribuerad.

AnvÀndaren kan ocksÄ ange antalet instanser av tjÀnsten i hela klustret och definiera ett predikat för att filtrera lÀmpliga noder. I ett sÄdant scenario berÀknar Service Grid sjÀlv den optimala distributionen för distribuerade tjÀnster.
Dessutom finns det en funktion som kallas Affinity Service. Affinity Àr en funktion som definierar kopplingen mellan nycklar och partitioner samt kopplingen mellan partitioner och noder i topologin. Genom nyckeln kan den primÀra noden faststÀllas dÀr data lagras. PÄ sÄ sÀtt kan din egen tjÀnst kopplas till nyckeln och cachen för affinity-funktionen. Vid en förÀndring av affinity-funktionen kommer en automatisk omdeployeringsprocess att ske. SÄledes kommer tjÀnsten alltid att placeras nÀra den data den ska manipulera, och dÀrmed minska overheadkostnaderna för att fÄ tillgÄng till information. Denna typ av schema kan kallas en form av kolokaliserade berÀkningar.
Nu nÀr vi har diskuterat vad som Àr fördelarna med Service Grid, lÄt oss prata om dess utvecklingshistoria.
Vad som var tidigare
Den tidigare implementeringen av Service Grid baserades pĂ„ en transaktionell replikerad systemcache Ignite. Med "cache" avses i Ignite ett datalager. Det Ă€r alltsĂ„ inte nĂ„got temporĂ€rt, som man kanske skulle kunna tro. Ăven om cachen Ă€r replikerad och varje nod innehĂ„ller hela datamĂ€ngden, har cachen en partitionerad representation. Detta Ă€r kopplat till optimering av lagringslösningar.

Vad hÀnde nÀr en anvÀndare ville distribuera en tjÀnst?
- Alla noder i klustret prenumererade pÄ uppdateringar av data i lagret med hjÀlp av den inbyggda mekanismen för Continuous Query.
- Initiatornoden gjorde en databaspost under en read-committed transaktion, som innehöll tjÀnstens konfiguration, inklusive en serialiserad instans.
- Vid mottagandet av en ny postberÀkning frÄn koordinatören berÀknades distributionen utifrÄn konfigurationen. Den erhÄllna objektet skrivs tillbaka till databasen.
- Om noden ingick i distributionen, hade koordinatören ansvar för att distribuera den.
Vad som inte tillfredsstÀllde oss
Vid en viss tidpunkt kom vi fram till att det inte gick att arbeta med tjÀnster pÄ det hÀr sÀttet. Det fanns flera anledningar.
Om det uppstod nĂ„got fel under distributionen kunde man endast fĂ„ information om det frĂ„n loggarna pĂ„ den nod dĂ€r hĂ€ndelsen intrĂ€ffade. Det fanns bara asynkron distribution, sĂ„ efter att kontrollen Ă„terstĂ€llts till anvĂ€ndaren frĂ„n distributionsmetoden behövdes viss extra tid för att starta tjĂ€nsten â under denna tid kunde anvĂ€ndaren inte hantera nĂ„got. För att vidareutveckla Service Grid, skapa nya funktioner, locka nya anvĂ€ndare och göra livet enklare för alla var förĂ€ndring nödvĂ€ndig.
Vid utformning av det nya Service Grid ville vi först och frÀmst erbjuda en garanti för synkron distribution: sÄ snart anvÀndaren fÄr kontrollen tillbaka frÄn API:et, kan hen omedelbart anvÀnda tjÀnsterna. Vi ville ocksÄ ge initiativtagaren möjlighet att hantera distributionsfel.
Dessutom ville vi underlÀtta implementeringen, nÀmligen avveckla transaktioner och ombalansering. Trots att cachen Àr replikerad och det inte finns nÄgon balans, uppstod problem under stora distributioner med mÄnga noder. Vid förÀndringar i topologin mÄste noderna utbyta information, och vid stora distributioner kan dessa uppgifter vÀga mycket.
NÀr topologin var instabil behövde koordinatoren omberÀkna fördelningen av tjÀnsterna. Och generellt sett, nÀr man mÄste arbeta med transaktioner pÄ en instabil topologi, kan det leda till svÄrförutsÀgbara fel.
Problem
Vilka globala förÀndringar skulle det vara utan medföljande problem? Den första av dessa var förÀndringen av topologin. Man mÄste förstÄ att i varje ögonblick, Àven under distributionen av en tjÀnst, kan en nod gÄ med i klustret eller lÀmna det. Dessutom, om en nod gÄr med i klustret under distributionen, mÄste all information om tjÀnsterna överföras konsekvent till den nya noden. Detta handlar inte bara om det som redan har distribuerats, utan ocksÄ om aktuella och framtida distributioner.
Detta Àr bara ett av problemen som kan samlas i en separat lista:
- Hur distribuerar man statiskt konfigurerade tjÀnster nÀr en nod startar?
- Vad ska man göra om en nod lÀmnar klustret och den hade hostat tjÀnster?
- Vad ska man göra om koordinatoren har bytts?
- Vad ska man göra om klienten kopplar om till klustret?
- MÄste aktiverings-/deaktiveringsförfrÄgningar bearbetas och hur?
- Och vad hÀnder om destruktorn för cachen anropades, men vi har affinitets-tjÀnster kopplade till den?
Och detta Àr lÄngt ifrÄn allt.
Lösning
Som mÄl valde vi en Event Driven-ansats med implementering av kommunikation mellan processer via meddelanden. I Ignite finns redan tvÄ komponenter som möjliggör att noder skickar meddelanden mellan varandra - communication-spi och discovery-spi.

Communication-spi möjliggör direkt kommunikation och meddelandeöverföring mellan noder. Det Àr vÀl lÀmpat för överföring av stora datamÀngder. Discovery-spi tillÄter att skicka ett meddelande till alla noder i klustret. I den standardimplementeringen görs detta enligt "ringtopologi". Det finns ocksÄ en integration med Zookeeper, dÀr "stjÀrntopologi" anvÀnds. En viktig punkt att nÀmna Àr att discovery-spi garanterar att meddelandet kommer att levereras i rÀtt ordning till alla noder.
LÄt oss övervÀga distributionsprotokollet. Alla anvÀndarförfrÄgningar om distribution och borttagning skickas via discovery-spi. Detta ger följande garantier:
- FörfrÄgan kommer att mottas av alla noder i klustret. Detta möjliggör fortsatt behandling av förfrÄgan vid byte av koordinator. Det betyder ocksÄ att varje nod, vid ett meddelande, fÄr all nödvÀndig metadata, som tjÀnsteconfig och dess serialiserade instans.
- Strikt ordning för meddelandeleverans möjliggör lösning av konfigurationskonflikter och konkurrerande förfrÄgningar.
- Eftersom noder som gÄr in i topologin ocksÄ hanteras via discovery-spi, fÄr den nya noden all nödvÀndig information för att arbeta med tjÀnster.
Vid mottagning av en förfrÄgan validerar noderna i klustret den och skapar uppgifter för bearbetning. Dessa uppgifter placeras i en kö och bearbetas sedan i en annan trÄd av en separat arbetare. Detta Àr implementerat pÄ detta sÀtt eftersom distribution kan ta betydande tid och försena den dyra discovery-flödet Àr oacceptabelt.
Alla förfrÄgningar frÄn kön bearbetas av distributionshanteraren. Den har en specialiserad arbetare som hÀmtar uppgiften frÄn denna kö och initierar den för att pÄbörja distributionen. Efter detta sker följande ÄtgÀrder:
- Varje nod berÀknar sjÀlvstÀndigt fördelningen baserat pÄ den nya deterministiska tilldelningsfunktionen.
- Noderna formar ett meddelande med resultaten av distributionen och skickar det till koordinatorn.
- Koordinatorn aggregerar alla meddelanden och formar resultatet av hela distributionsprocessen, vilket skickas via discovery-spi till alla noder i klustret.
- Vid mottagning av resultatet avslutas distributionsprocessen, varefter uppgiften tas bort frÄn kön.

Ny event-driven design: org.apache.ignite.internal.processors.service.IgniteServiceProcessor.java
Om ett fel intrÀffar vid distributionen, inkluderar noden omedelbart detta fel i meddelandet som skickas till koordinatorn. Efter aggregationen av meddelanden kommer koordinatorn att ha information om alla fel under distributionen och skicka detta meddelande via discovery-spi. Information om felen kommer att vara tillgÀnglig pÄ vilken nod som helst i klustret.
Alla viktiga hÀndelser i Service Grid bearbetas enligt denna algoritm. Till exempel, en toppologiförÀndring Àr ocksÄ ett meddelande via discovery-spi. Generellt sett, jÀmfört med vad som fanns tidigare, har protokollet blivit tillrÀckligt lÀttviktigt och pÄlitligt. TillrÀckligt för att hantera alla situationer under distributionen.
Vad som kommer hÀrnÀst
Nu om planerna. Varje större förbÀttring i projektet Ignite genomförs som en insats för att förbÀttra Ignite, sÄ kallad IEP. Redesignen av Service Grid har ocksÄ en IEP - med ett skÀmtsamt namn "Byte av olja i Service Grid". Men i sjÀlva verket har vi inte bara bytt olja i motorn, utan hela motorn.
Vi har delat upp uppgifterna i IEP i tvÄ faser. Första fasen Àr en stor fas som gÄr ut pÄ att omarbeta distributionsprotokollet. Den har redan slagits samman med huvudgrenen, sÄ man kan prova den nya Service Grid som kommer i version 2.8. Den andra fasen inkluderar mÄnga andra uppgifter:
- Hot-swap-distribution
- Versionshantering av tjÀnster
- Ăkad felresiliens
- Tunn klient
- Ăvervakningsverktyg och mĂ€tning av olika metrikser
Avslutningsvis kan vi rekommendera Service Grid för att bygga felresistenta system med hög tillgÀnglighet. Vi bjuder ocksÄ in er till och för att dela med er av er erfarenhet. Er erfarenhet Àr verkligen viktig för gemenskapen, den hjÀlper till att förstÄ i vilken riktning vi ska gÄ vidare och hur vi kan utveckla komponenten framöver.
KĂ€lla: habr.com
