Introduktion til Apache Curator

1. Introduktion

Apache Curator er en Java-klient til Apache Zookeeper, den populære koordinationstjeneste til distribuerede applikationer.

I denne vejledning introducerer vi nogle af de mest relevante funktioner leveret af kurator:

  • Forbindelsesstyring - styring af forbindelser og prøv igen politikker
  • Async - forbedring af eksisterende klient ved at tilføje async-funktioner og brug af Java 8 lambdas
  • Configuration Management - har en central konfiguration til systemet
  • Stærkt typede modeller - arbejder med typede modeller
  • Opskrifter - implementering af ledervalg, distribuerede låse eller skranker

2. Forudsætninger

Til at begynde med anbefales det at kigge hurtigt på Apache Zookeeper og dens funktioner.

Til denne tutorial antager vi, at der allerede er en enkeltstående Zookeeper-instans, der kører på 127.0.0.1:2181; her er instruktioner om, hvordan du installerer og kører det, hvis du lige er kommet i gang.

Først skal vi tilføje curator-x-async-afhængighed til vores pom.xml:

 org.apache.curator curator-x-async 4.0.1 org.apache.zookeeper zookeeper 

Den seneste version af Apache Curator 4.X.X har en hård afhængighed af Zookeeper 3.5.X som stadig er i beta lige nu.

Og så, i denne artikel skal vi bruge den aktuelt seneste stabile Zookeeper 3.4.11 i stedet.

Så vi er nødt til at udelukke Zookeeper-afhængigheden og føje afhængigheden af ​​vores Zookeeper-version til vores pom.xml:

 org.apache.zookeeper zookeeper 3.4.11 

For mere information om kompatibilitet henvises til dette link.

3. Forbindelsesstyring

Den basale anvendelse af Apache Curator er at oprette forbindelse til en kørende Apache Zookeeper-forekomst.

Værktøjet giver en fabrik til at oprette forbindelser til Zookeeper ved hjælp af forsøgspolitikker:

int sleepMsBetweenRetries = 100; int maxRetries = 3; RetryPolicy retryPolicy = nyt RetryNTimes (maxRetries, sleepMsBetweenRetries); CuratorFramework-klient = CuratorFrameworkFactory .newClient ("127.0.0.1:2181", retryPolicy); client.start (); assertThat (client.checkExists (). forPath ("/")). erNotNull ();

I dette hurtige eksempel prøver vi igen 3 gange og venter 100 ms mellem forsøg igen i tilfælde af forbindelsesproblemer.

Når du er tilsluttet Zookeeper ved hjælp af CuratorFramework klient, kan vi nu gennemse stier, hente / indstille data og i det væsentlige interagere med serveren.

4. Asynkronisering

Curator Async-modulet omslutter ovenstående CuratorFramework klient til at levere ikke-blokerende muligheder ved hjælp af CompletionStage Java 8 API.

Lad os se, hvordan det foregående eksempel ser ud ved at bruge Async-indpakningen:

int sleepMsBetweenRetries = 100; int maxRetries = 3; RetryPolicy retryPolicy = nyt RetryNTimes (maxRetries, sleepMsBetweenRetries); CuratorFramework-klient = CuratorFrameworkFactory .newClient ("127.0.0.1:2181", retryPolicy); client.start (); AsyncCuratorFramework async = AsyncCuratorFramework.wrap (klient); AtomicBoolean findes = ny AtomicBoolean (falsk); async.checkExists () .forPath ("/"). derefterAcceptAsync (s -> eksisterer. sæt (s! = null)); afventer (). indtil (() -> hævder, at (eksisterer. får ()). er sand ());

Nu, den checkExists () operation fungerer i asynkron tilstand og blokerer ikke hovedtråden. Vi kan også kæde handlinger efter hinanden ved hjælp af thenAcceptAsync () metode i stedet, som bruger CompletionStage API.

5. Konfigurationsstyring

I et distribueret miljø er en af ​​de mest almindelige udfordringer at styre delt konfiguration blandt mange applikationer. Vi kan bruge Zookeeper som et datalager, hvor vores konfiguration skal holdes.

Lad os se et eksempel ved hjælp af Apache Curator til at hente og indstille data:

CuratorFramework-klient = newClient (); client.start (); AsyncCuratorFramework async = AsyncCuratorFramework.wrap (klient); Strengnøgle = getKey (); Streng forventet = "min_værdi"; client.create (). forPath (nøgle); async.setData () .forPath (nøgle, forventet.getBytes ()); AtomicBoolean isEquals = ny AtomicBoolean (); async.getData () .forPath (nøgle) .thenAccept (data -> isEquals.set (ny streng (data). ligestillinger (forventet))); afvente (). indtil (() -> assertThat (isEquals.get ()). isTrue ());

I dette eksempel opretter vi nodestien, indstiller dataene i Zookeeper, og derefter genopretter vi den og kontrollerer, at værdien er den samme. Det nøgle felt kunne være en nodesti som / config / dev / my_key.

5.1. Vagter

En anden interessant funktion i Zookeeper er evnen til at se nøgler eller noder. Det giver os mulighed for at lytte til ændringer i konfigurationen og opdatere vores applikationer uden at skulle omplacere.

Lad os se, hvordan ovenstående eksempel ser ud, når du bruger watchers:

CuratorFramework-klient = newClient () client.start (); AsyncCuratorFramework async = AsyncCuratorFramework.wrap (klient); Strengnøgle = getKey (); Streng forventet = "min_værdi"; async.create (). for Path (nøgle); Listeændringer = ny ArrayList (); async.watched () .getData () .forPath (nøgle) .event () .thenAccept (WatchEvent -> {prøv {ændringer.add (ny streng (client.getData () .forPath (WatchEvent.getPath ())) ;} fange (Undtagelse e) {// mislykkes ...}}); // Indstil dataværdi for vores nøgle async.setData () .forPath (nøgle, forventet.getBytes ()); afventer () .tiltil (() -> hævder, at (ændringer.størrelse ()). erEqualTo (1));

Vi konfigurerer seeren, indstiller dataene og bekræfter derefter, at den overvågede begivenhed blev udløst. Vi kan se en node eller et sæt noder på én gang.

6. Stærkt typede modeller

Zookeeper fungerer primært med byte-arrays, så vi er nødt til at serialisere og deserialisere vores data. Dette giver os en vis fleksibilitet til at arbejde med enhver seriøs forekomst, men det kan være svært at vedligeholde.

For at hjælpe her tilføjer Curator konceptet med typede modeller, som delegerer serialisering / deserialisering og giver os mulighed for at arbejde med vores typer direkte. Lad os se, hvordan det fungerer.

For det første har vi brug for en serialiseringsramme. Curator anbefaler at bruge Jackson-implementeringen, så lad os tilføje Jackson-afhængigheden til vores pom.xml:

 com.fasterxml.jackson.core jackson-databind 2.9.4 

Lad os nu prøve at fortsætte vores brugerdefinerede klasse HostConfig:

offentlig klasse HostConfig {privat strengværtsnavn; privat int port; // getters og setters}

Vi er nødt til at give kortlægning af modelspecifikation fra HostConfig klasse til en sti, og brug den modellerede rammeindpakning, der leveres af Apache Curator:

ModelSpec mySpec = ModelSpec.builder (ZPath.parseWithIds ("/ config / dev"), JacksonModelSerializer.build (HostConfig.class)) .build (); CuratorFramework-klient = newClient (); client.start (); AsyncCuratorFramework async = AsyncCuratorFramework.wrap (klient); ModeledFramework modeledClient = ModeledFramework.wrap (async, mySpec); modeledClient.set (nyt HostConfig ("værtsnavn", 8080)); modeledClient.read () .whenComplete ((værdi, e) -> {hvis (e! = null) {fail ("Kan ikke læse værtskonfiguration", e);} ellers {assertThat (værdi) .isNotNull (); assertThat ( value.getHostname ()). isEqualTo ("host-name"); assertThat (value.getPort ()). isEqualTo (8080);}});

Det nårFuldfør () metode, når du læser stien / config / dev vil returnere HostConfig eksempel i Zookeeper.

7. Opskrifter

Zookeeper giver denne retningslinje til implementering løsninger på højt niveau eller opskrifter såsom ledervalg, distribuerede låse eller delte tællere.

Apache Curator giver en implementering af de fleste af disse opskrifter. For at se den fulde liste skal du besøge Curator Recipes-dokumentationen.

Alle disse opskrifter er tilgængelige i et separat modul:

 org.apache.curator kurator-opskrifter 4.0.1 

Lad os hoppe lige ind og begynde at forstå disse med nogle enkle eksempler.

7.1. Valg af leder

I et distribueret miljø har vi muligvis brug for en master- eller lederknude til at koordinere et komplekst job.

Sådan ser brugen af ​​ledervalgopskriften i kurator ud:

CuratorFramework-klient = newClient (); client.start (); LeaderSelector leaderSelector = ny LeaderSelector (klient, "/ mutex / select / leader / for / job / A", ny LeaderSelectorListener () {@Override public void stateChanged (CuratorFramework client, ConnectionState newState) {} @Override public void takeLeadership (CuratorFramework client kaster undtagelse {}}); // slutte sig til medlemmets gruppelederSelector.start (); // vent, indtil jobbet A er udført blandt alle medlemmer leaderSelector.close ();

Når vi starter ledervælgeren, slutter vores node sig til en medlemsgruppe inden for stien / mutex / vælg / leder / til / job / A.. Når vores node bliver leder, bliver tage lederskab metode vil blive påberåbt, og vi som ledere kan genoptage jobbet.

7.2. Delt låse

Delt lås opskrift handler om at have en fuldt distribueret lås:

CuratorFramework-klient = newClient (); client.start (); InterProcessSemaphoreMutex sharedLock = ny InterProcessSemaphoreMutex (klient, "/ mutex / process / A"); sharedLock.acquire (); // behandle en sharedLock.release ();

Når vi erhverver låsen, sikrer Zookeeper, at der ikke er nogen anden applikation, der erhverver den samme lås på samme tid.

7.3. Tællere

Counters-opskriften koordinerer en delt Heltal blandt alle klienter:

CuratorFramework-klient = newClient (); client.start (); SharedCount-tæller = ny SharedCount (klient, "/ counters / A", 0); counter.start (); counter.setCount (counter.getCount () + 1); assertThat (counter.getCount ()). er EqualTo (1);

I dette eksempel gemmer Zookeeper Heltal værdi i stien / tællere / A og initialiserer værdien til 0 hvis stien endnu ikke er oprettet.

8. Konklusion

I denne artikel har vi set, hvordan man bruger Apache Curator til at oprette forbindelse til Apache Zookeeper og drage fordel af dens vigtigste funktioner.

Vi har også introduceret et par af de vigtigste opskrifter i Curator.

Som sædvanligt kan kilder findes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found