Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka

Nadaljevanje prevoda knjižice:
Razumevanje posrednikov sporočil
avtor: Jakub Korab, založba: O'Reilly Media, Inc., datum izida: junij 2017, ISBN: 9781492049296.

Prejšnji prevedeni del: Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. Poglavje 1 Uvod

POGLAVJE 3

Kafka

Kafka je bil razvit v LinkedInu, da bi se izognil nekaterim omejitvam tradicionalnih posrednikov sporočil in se izognil nastavitvi več posrednikov sporočil za različne interakcije od točke do točke, kar je opisano v tej knjigi pod "Povečanje in zmanjšanje" na strani 28. Primeri uporabe LinkedIn se je v veliki meri zanašal na enosmerno zaužitje zelo velikih količin podatkov, kot so kliki strani in dnevniki dostopov, hkrati pa je še vedno omogočal, da te podatke uporablja več sistemov, ne da bi to vplivalo na produktivnost proizvajalcev ali drugih potrošnikov. Pravzaprav je razlog, zakaj Kafka obstaja, ta, da bi dobil takšno arhitekturo sporočanja, kot jo opisuje Universal Data Pipeline.

Glede na ta končni cilj so se seveda pojavile druge zahteve. Kafka bi moral:

  • Bodite izjemno hitri
  • Zagotovite večjo pasovno širino pri delu s sporočili
  • Podpira modele Publisher-Subscriber in Point-to-Point
  • Ne upočasnjujte z dodajanjem potrošnikov. Zmogljivost tako čakalne vrste kot teme v ActiveMQ se na primer poslabša, ko raste število porabnikov na cilju.
  • Bodite vodoravno razširljivi; če lahko en posrednik, ki obdrži sporočila, to stori le pri največji hitrosti diska, potem je smiselno preseči en primerek posrednika, da povečate zmogljivost
  • Omejite dostop do shranjevanja in ponovnega pridobivanja sporočil

Da bi vse to dosegel, je Kafka sprejel arhitekturo, ki je na novo definirala vloge in odgovornosti strank in posrednikov za sporočanje. Model JMS je zelo usmerjen k posredniku, kjer je posrednik odgovoren za distribucijo sporočil, stranke pa morajo skrbeti samo za pošiljanje in prejemanje sporočil. Po drugi strani pa je Kafka osredotočen na odjemalca, pri čemer odjemalec prevzame številne lastnosti tradicionalnega posrednika, kot je pravična distribucija ustreznih sporočil potrošnikom, v zameno za izjemno hitrega in razširljivega posrednika. Za ljudi, ki so delali s tradicionalnimi sistemi sporočanja, delo s Kafko zahteva temeljno spremembo mišljenja.
Ta inženirska usmeritev je privedla do ustvarjanja infrastrukture za sporočanje, ki je sposobna povečati prepustnost za več stopenj velikosti v primerjavi z običajnim posrednikom. Kot bomo videli, ta pristop vključuje kompromise, kar pomeni, da Kafka ni primerna za določene vrste delovnih obremenitev in nameščene programske opreme.

Enotni ciljni model

Da bi izpolnil zgoraj opisane zahteve, je Kafka združil objavo-naročitev in sporočanje od točke do točke pod eno vrsto cilja − tema. To zmede ljudi, ki so delali s sistemi za sporočanje, kjer se beseda "tema" nanaša na mehanizem oddajanja, iz katerega (iz teme) branje ni trajno. Teme Kafke je treba obravnavati kot vrsto hibridne destinacije, kot je opredeljeno v uvodu te knjige.

V preostalem delu tega poglavja, razen če izrecno navedemo drugače, se bo izraz "tema" nanašal na Kafkovo temo.

Da bi popolnoma razumeli, kako se teme obnašajo in kakšna jamstva dajejo, moramo najprej pogledati, kako so implementirane v Kafki.
Vsaka tema v Kafki ima svoj dnevnik.
Proizvajalci, ki pošiljajo sporočila Kafki, pišejo v ta dnevnik, potrošniki pa berejo iz dnevnika z uporabo kazalcev, ki se nenehno premikajo naprej. Kafka občasno izbriše najstarejše dele dnevnika, ne glede na to, ali so bila sporočila v teh delih prebrana ali ne. Osrednji del Kafkine zasnove je, da posredniku ni vseeno, ali so sporočila prebrana ali ne – to je odgovornost stranke.

Izraza "log" in "kazalec" se ne pojavita v Kafkova dokumentacija. Ti dobro znani izrazi so tukaj uporabljeni za lažje razumevanje.

Ta model je popolnoma drugačen od ActiveMQ, kjer so sporočila iz vseh čakalnih vrst shranjena v istem dnevniku, posrednik pa sporočila po branju označi kot izbrisana.
Poglobimo se zdaj in si podrobneje oglejmo dnevnik teme.
Kafkov dnevnik je sestavljen iz več particij (Slika 3-1). Kafka zagotavlja strog red v vsaki particiji. To pomeni, da bodo sporočila, zapisana v particijo v določenem vrstnem redu, prebrana v istem vrstnem redu. Vsaka particija je implementirana kot tekoča dnevniška datoteka, ki vsebuje podnabor (podmnožica) vseh sporočil, ki so jih avtorji poslali na temo. Ustvarjena tema privzeto vsebuje eno particijo. Zamisel o predelnih stenah je osrednja ideja Kafke za horizontalno skaliranje.

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-1. Kafka Predelne stene

Ko proizvajalec pošlje sporočilo temi Kafka, se odloči, v katero particijo bo poslal sporočilo. To si bomo podrobneje ogledali kasneje.

Branje sporočil

Odjemalec, ki želi prebrati sporočila, upravlja klicani imenovani kazalec skupino potrošnikov, ki kaže na odmik sporočila v particiji. Odmik je inkrementalni položaj, ki se začne pri 0 na začetku particije. Ta skupina potrošnikov, navedena v API-ju prek uporabniško definiranega group_id, ustreza enega logičnega porabnika ali sistema.

Večina sistemov za sporočanje bere podatke iz cilja z uporabo več primerkov in niti za vzporedno obdelavo sporočil. Tako bo običajno veliko potrošniških primerkov, ki si delijo isto potrošniško skupino.

Problem branja je mogoče predstaviti na naslednji način:

  • Tema ima več particij
  • Več skupin potrošnikov lahko istočasno uporablja temo
  • Skupina porabnikov ima lahko več ločenih primerkov

To je netrivialni problem veliko proti mnogo. Da bi razumeli, kako Kafka obravnava odnose med potrošniškimi skupinami, potrošniškimi instancami in particijami, si poglejmo niz postopoma bolj zapletenih scenarijev branja.

Potrošniki in skupine potrošnikov

Za izhodišče vzemimo temo z eno particijo (Slika 3-2).

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-2. Potrošnik bere iz particije

Ko se primerek potrošnika poveže s svojim lastnim group_id s to temo, se ji dodeli particija za branje in odmik v tej particiji. Položaj tega odmika je v odjemalcu konfiguriran kot kazalec na najnovejši položaj (najnovejše sporočilo) ali najzgodnejši položaj (najstarejše sporočilo). Potrošnik zahteva (anketira) sporočila iz teme, kar povzroči njihovo zaporedno branje iz dnevnika.
Položaj zamika se redno vrne Kafki in shrani kot sporočila v interni temi _potrošniški_odbitki. Prebrana sporočila se še vedno ne izbrišejo, za razliko od običajnega posrednika, odjemalec pa lahko previje odmik nazaj, da ponovno obdela že ogledana sporočila.

Ko se drugi logični porabnik poveže z uporabo drugega group_id, upravlja drugi kazalec, ki je neodvisen od prvega (Slika 3-3). Tako tema Kafke deluje kot čakalna vrsta, kjer je en uporabnik, in kot običajna tema objave-naročila (pub-sub), na katero se naroči več potrošnikov, z dodatno prednostjo, da so vsa sporočila shranjena in jih je mogoče večkrat obdelati.

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-3. Dva porabnika v različnih skupinah porabnikov bereta iz iste particije

Potrošniki v potrošniški skupini

Ko en porabniški primerek prebere podatke iz particije, ima popoln nadzor nad kazalcem in obdeluje sporočila, kot je opisano v prejšnjem razdelku.
Če je bilo več primerkov porabnikov povezanih z istim group_id na temo z eno particijo, bo primerek, ki se je zadnji povezal, dobil nadzor nad kazalcem in od tega trenutka naprej bo prejemal vsa sporočila (Slika 3-4).

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-4. Dva porabnika v isti skupini porabnikov bereta iz iste particije

Ta način obdelave, pri katerem število porabniških primerkov presega število particij, lahko razumemo kot neke vrste izključnega porabnika. To je lahko uporabno, če potrebujete "aktivno-pasivno" (ali "vroče-toplo") združevanje v gruče svojih porabniških primerkov, čeprav je vzporedno izvajanje več porabnikov ("aktivno-aktivno" ali "vroče-vroče") veliko bolj običajno kot porabniki V pripravljenosti.

To vedenje distribucije sporočil, opisano zgoraj, je lahko presenetljivo v primerjavi s tem, kako se obnaša običajna čakalna vrsta JMS. V tem modelu bodo sporočila, poslana v čakalno vrsto, enakomerno porazdeljena med oba porabnika.

Najpogosteje, ko ustvarimo več primerkov porabnikov, to naredimo bodisi za vzporedno obdelavo sporočil bodisi za povečanje hitrosti branja ali za povečanje stabilnosti procesa branja. Kako je to doseženo v Kafki, ker lahko podatke iz particije bere samo en primerek potrošnika hkrati?

Eden od načinov za to je uporaba enega samega primerka potrošnika za branje vseh sporočil in njihovo posredovanje v področje niti. Medtem ko ta pristop poveča prepustnost obdelave, poveča kompleksnost potrošniške logike in nič ne poveča robustnosti sistema za branje. Če zaradi izpada električne energije ali podobnega dogodka ena kopija porabnika izpade, se odštevanje ustavi.

Kanonični način za rešitev tega problema pri Kafki je uporaba bОveč particij.

Particioniranje

Particije so glavni mehanizem za vzporedno branje in skaliranje teme prek pasovne širine posamezne instance posrednika. Da bi to bolje razumeli, razmislimo o situaciji, ko obstaja tema z dvema razdelkoma in se en uporabnik naroči na to temo (Slika 3-5).

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-5. En porabnik bere iz več particij

V tem scenariju dobi potrošnik nadzor nad kazalci, ki ustrezajo njegovemu group_id v obeh particijah, in začne brati sporočila iz obeh particij.
Ko je v to temo dodan dodatni porabnik za isti group_id, Kafka prerazporedi eno od particij s prvega na drugega porabnika. Nato bo vsak primerek potrošnika bral iz ene particije teme (Slika 3-6).

Če želite zagotoviti, da se sporočila obdelujejo vzporedno v 20 nitih, potrebujete vsaj 20 particij. Če je particij manj, boste ostali s porabniki, ki nimajo na čem delati, kot je opisano prej v razpravi o izključnih porabnikih.

Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. 3. poglavje. Kafka
Slika 3-6. Dva porabnika v isti porabniški skupini bereta iz različnih particij

Ta shema močno zmanjša kompleksnost posrednika Kafka v primerjavi z distribucijo sporočil, ki je potrebna za vzdrževanje čakalne vrste JMS. Tukaj vam ni treba skrbeti za naslednje točke:

  • Kateri porabnik naj prejme naslednje sporočilo, na podlagi krožne dodelitve, trenutne zmogljivosti vmesnih pomnilnikov za vnaprejšnje pridobivanje ali prejšnjih sporočil (kot za skupine sporočil JMS).
  • Katera sporočila so poslana katerim potrošnikom in ali jih je treba v primeru napake ponovno dostaviti.

Vse, kar mora posrednik Kafka storiti, je, da potrošniku zaporedno posreduje sporočila, ko jih ta zahteva.

Vendar zahteve po vzporednem branju in ponovnem pošiljanju neuspelih sporočil ne izginejo - odgovornost zanje preprosto preide s posrednika na naročnika. To pomeni, da jih je treba upoštevati v vaši kodi.

Pošiljanje sporočil

Proizvajalec tega sporočila je odgovoren, da se odloči, kateri particiji bo poslal sporočilo. Da bi razumeli mehanizem, s katerim to poteka, moramo najprej razmisliti, kaj točno pravzaprav pošiljamo.

Medtem ko v JMS uporabljamo strukturo sporočila z metapodatki (glave in lastnosti) in telo, ki vsebuje vsebino (payload), je v Kafki sporočilo par "ključ-vrednost". Tovor sporočila se pošlje kot vrednost. Ključ pa se uporablja predvsem za particioniranje in mora vsebovati specifičen ključ poslovne logikeda sorodna sporočila postavite v isto particijo.

V 2. poglavju smo razpravljali o scenariju spletnih stav, kjer mora povezane dogodke po vrstnem redu obdelati en sam potrošnik:

  1. Uporabniški račun je konfiguriran.
  2. Denar se nakaže na račun.
  3. Sklene se stava, ki dvigne denar z računa.

Če je vsak dogodek sporočilo, objavljeno v temi, bi bil naravni ključ ID računa.
Ko je sporočilo poslano z API-jem Kafka Producer, se posreduje particijski funkciji, ki glede na sporočilo in trenutno stanje gruče Kafka vrne ID particije, v katero naj bo sporočilo poslano. Ta funkcija je implementirana v Javi prek vmesnika Partitioner.

Ta vmesnik izgleda takole:

interface Partitioner {
    int partition(String topic,
        Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
}

Implementacija Partitionerja uporablja privzeti splošni algoritem zgoščevanja nad ključem za določitev particije ali krožno, če ključ ni določen. Ta privzeta vrednost v večini primerov deluje dobro. Vendar pa boste v prihodnosti želeli napisati svoje.

Pisanje lastne strategije particioniranja

Oglejmo si primer, kjer želite poslati metapodatke skupaj s tovorom sporočila. Tovor v našem primeru je navodilo za nakazilo na račun igre. Navodilo je nekaj, za kar želimo zagotoviti, da se ob prenosu ne bo spremenilo, in želimo biti prepričani, da lahko samo zaupanja vreden sistem navzgor sproži to navodilo. V tem primeru se sistem za pošiljanje in sprejem dogovorita o uporabi podpisa za avtentikacijo sporočila.
V običajnem JMS preprosto definiramo lastnost "podpis sporočila" in jo dodamo sporočilu. Vendar nam Kafka ne ponuja mehanizma za posredovanje metapodatkov, temveč le ključ in vrednost.

Ker je vrednost koristni tovor bančnega nakazila, katerega celovitost želimo ohraniti, nimamo druge izbire, kot da definiramo podatkovno strukturo, ki jo bomo uporabili v ključu. Ob predpostavki, da za particioniranje potrebujemo ID računa, ker morajo biti vsa sporočila, povezana z računom, obdelana po vrstnem redu, bomo dobili naslednjo strukturo JSON:

{
  "signature": "541661622185851c248b41bf0cea7ad0",
  "accountId": "10007865234"
}

Ker se bo vrednost podpisa razlikovala glede na obremenitev, privzeta strategija zgoščevanja vmesnika Partitioner ne bo zanesljivo združila povezanih sporočil. Zato bomo morali napisati lastno strategijo, ki bo razčlenila ta ključ in razdelila vrednost accountId.

Kafka vključuje kontrolne vsote za odkrivanje poškodovanosti sporočil v trgovini in ima celoten nabor varnostnih funkcij. Kljub temu se včasih pojavijo zahteve, specifične za panogo, kot je zgornja.

Uporabnikova strategija particioniranja mora zagotoviti, da se vsa povezana sporočila končajo v isti particiji. Čeprav se to zdi preprosto, je zahteva lahko zapletena zaradi pomembnosti naročanja povezanih objav in tega, kako fiksno je število particij v temi.

Število particij v temi se lahko sčasoma spremeni, saj jih je mogoče dodati, če promet preseže prvotna pričakovanja. Tako je mogoče ključe sporočil povezati s particijo, v katero so bili prvotno poslani, kar pomeni del stanja, ki se deli med instancami proizvajalca.

Drug dejavnik, ki ga je treba upoštevati, je enakomerna porazdelitev sporočil po particijah. Običajno ključi niso enakomerno porazdeljeni po sporočilih, zgoščevalne funkcije pa ne zagotavljajo pravične porazdelitve sporočil za majhen nabor ključev.
Pomembno je vedeti, da bo morda treba znova uporabiti ločilo, ne glede na to, kako se odločite za razdelitev sporočil.

Upoštevajte zahtevo po podvajanju podatkov med grozdi Kafka na različnih geografskih lokacijah. V ta namen ima Kafka orodje ukazne vrstice, imenovano MirrorMaker, ki se uporablja za branje sporočil iz ene gruče in njihov prenos v drugo.

MirrorMaker mora razumeti ključe podvojene teme, da ohrani relativni red med sporočili pri podvajanju med gručami, saj število particij za to temo morda ni enako v dveh gručah.

Strategije particioniranja po meri so razmeroma redke, saj privzeto zgoščevanje ali kroženje dobro deluje v večini scenarijev. Če pa potrebujete močna jamstva za naročanje ali morate ekstrahirati metapodatke iz uporabnih obremenitev, potem je particioniranje nekaj, čemur bi morali podrobneje ogledati.

Razširljivost in prednosti Kafke izhajajo iz prenosa nekaterih odgovornosti tradicionalnega posrednika na stranko. V tem primeru se sprejme odločitev o distribuciji potencialno sorodnih sporočil med več potrošnikov, ki delujejo vzporedno.

S takimi zahtevami se morajo ukvarjati tudi posredniki JMS. Zanimivo je, da mehanizem za pošiljanje povezanih sporočil istemu uporabniku, implementiran prek JMS Message Groups (različica strategije lepljivega uravnoteženja obremenitve (SLB)), prav tako zahteva, da pošiljatelj označi sporočila kot povezana. V primeru JMS je posrednik odgovoren za pošiljanje te skupine povezanih sporočil enemu od mnogih potrošnikov in prenos lastništva skupine, če potrošnik odpade.

Producentski sporazumi

Razdelitev ni edina stvar, ki jo morate upoštevati pri pošiljanju sporočil. Oglejmo si metode send() razreda Producer v Java API:

Future < RecordMetadata > send(ProducerRecord < K, V > record);
Future < RecordMetadata > send(ProducerRecord < K, V > record, Callback callback);

Takoj je treba opozoriti, da obe metodi vrneta prihodnost, kar pomeni, da se operacija pošiljanja ne izvede takoj. Rezultat tega je, da se sporočilo (ProducerRecord) zapiše v medpomnilnik za pošiljanje za vsako aktivno particijo in pošlje posredniku kot nit v ozadju v odjemalski knjižnici Kafka. Čeprav so zaradi tega stvari neverjetno hitre, to pomeni, da lahko neizkušena aplikacija izgubi sporočila, če je njen proces ustavljen.

Kot vedno obstaja način, da naredite operacijo pošiljanja bolj zanesljivo za ceno zmogljivosti. Velikost tega vmesnega pomnilnika je mogoče nastaviti na 0 in nit aplikacije, ki pošilja, bo prisiljena počakati, da se prenos sporočila do posrednika zaključi, kot sledi:

RecordMetadata metadata = producer.send(record).get();

Več o branju sporočil

Branje sporočil ima dodatne zapletenosti, o katerih je treba špekulirati. Za razliko od API-ja JMS, ki lahko zažene poslušalnik sporočil kot odgovor na sporočilo, je Potrošniška Kafka samo ankete. Oglejmo si podrobneje metodo anketa()uporabljeno za ta namen:

ConsumerRecords < K, V > poll(long timeout);

Povratna vrednost metode je struktura vsebnika, ki vsebuje več predmetov potrošniški zapis iz potencialno več particij. potrošniški zapis je sam objekt imetnika za par ključ-vrednost s povezanimi metapodatki, kot je particija, iz katere je izpeljan.

Kot je bilo razloženo v 2. poglavju, moramo imeti v mislih, kaj se zgodi s sporočili, potem ko so bila uspešno ali neuspešno obdelana, na primer, če odjemalec ne more obdelati sporočila ali če se prekine. V JMS je bilo to obravnavano v načinu potrditve. Posrednik bo bodisi izbrisal uspešno obdelano sporočilo bodisi ponovno dostavil neobdelano ali lažno sporočilo (ob predpostavki, da so bile uporabljene transakcije).
Kafka deluje zelo drugače. Sporočila se v posredniku po lektoriranju ne izbrišejo, za dogajanje ob neuspehu pa je odgovorna sama lektorska koda.

Kot smo rekli, je skupina potrošnikov povezana z odmikom v dnevniku. Položaj dnevnika, povezan s tem odmikom, ustreza naslednjemu sporočilu, ki bo izdano kot odgovor anketa(). Časovna točka, ko se ta odmik poveča, je odločilna za branje.

Če se vrnemo k modelu branja, o katerem smo govorili prej, je obdelava sporočil sestavljena iz treh stopenj:

  1. Pridobite sporočilo za branje.
  2. Obdelajte sporočilo.
  3. Potrdite sporočilo.

Potrošnik Kafka ima možnost konfiguracije enable.auto.commit. To je pogosto uporabljena privzeta nastavitev, kot je običajno pri nastavitvah, ki vsebujejo besedo "samodejno".

Pred Kafko 0.10 je odjemalec, ki uporablja to možnost, ob naslednjem klicu poslal odmik zadnjega prebranega sporočila anketa() po obdelavi. To je pomenilo, da je bilo mogoče vsa sporočila, ki so bila že pridobljena, ponovno obdelati, če jih je odjemalec že obdelal, vendar je bilo pred klicem nepričakovano uničeno anketa(). Ker posrednik ne hrani nobenega stanja o tem, kolikokrat je bilo sporočilo prebrano, naslednji potrošnik, ki pridobi to sporočilo, ne bo vedel, da se je zgodilo kaj slabega. To vedenje je bilo psevdotransakcijsko. Odmik je bil storjen le, če je bilo sporočilo uspešno obdelano, če pa je odjemalec prekinil, bi posrednik isto sporočilo znova poslal drugemu odjemalcu. To vedenje je bilo v skladu z garancijo za dostavo sporočil "vsaj enkrat".

V Kafki 0.10 je bila koda odjemalca spremenjena tako, da knjižnica odjemalca občasno sproži objavo, kot je konfigurirano auto.commit.interval.ms. To vedenje je nekje med načinoma JMS AUTO_ACKNOWLEDGE in DUPS_OK_ACKNOWLEDGE. Pri uporabi samodejne potrditve se lahko sporočila potrdijo ne glede na to, ali so bila dejansko obdelana – to se lahko zgodi v primeru počasnega uporabnika. Če bi porabnik prekinil, bi sporočila pridobil naslednji porabnik, začenši na dodeljenem položaju, kar bi lahko povzročilo zgrešeno sporočilo. V tem primeru Kafka sporočil ni izgubil, le bralna koda jih ni obdelala.

Ta način ima isto obljubo kot v različici 0.9: sporočila je mogoče obdelati, če pa ne uspe, odmik morda ne bo potrjen, kar lahko povzroči podvojitev dostave. Več sporočil pridobite med izvajanjem anketa(), večja je ta težava.

Kot je razloženo v “Branje sporočil iz čakalne vrste” na strani 21, ne obstaja stvar, kot je enkratna dostava sporočila v sistemu za sporočanje, če se upoštevajo načini napak.

V Kafki obstajata dva načina za zavezovanje (zaveza) odmika (pobota): samodejno in ročno. V obeh primerih je mogoče sporočila obdelati večkrat, če je bilo sporočilo obdelano, vendar ni uspelo pred potrditvijo. Lahko se tudi odločite, da sporočila sploh ne obdelate, če se je potrditev zgodila v ozadju in je bila vaša koda dokončana, preden jo je bilo mogoče obdelati (morda v Kafki 0.9 in starejših).

Z nastavitvijo parametra lahko nadzirate postopek odobritve ročnega odmika v potrošniškem API-ju Kafka enable.auto.commit na false in izrecno kliče eno od naslednjih metod:

void commitSync();
void commitAsync();

Če želite sporočilo obdelati "vsaj enkrat", morate odmik potrditi ročno z commitSync()z izvedbo tega ukaza takoj po obdelavi sporočil.

Te metode ne dovoljujejo potrditve sporočil, preden so obdelana, vendar ne naredijo ničesar za odpravo morebitnih zamud pri obdelavi, hkrati pa dajejo videz transakcije. V Kafki ni transakcij. Stranka nima možnosti narediti naslednjega:

  • Samodejno razveljavi ponarejeno sporočilo. Potrošniki morajo sami obravnavati izjeme, ki izhajajo iz problematičnih obremenitev in izpadov v zaledju, saj se ne morejo zanesti na posrednika, da bo ponovno dostavil sporočila.
  • Pošljite sporočila na več tem v eni atomski operaciji. Kot bomo kmalu videli, se lahko nadzor nad različnimi temami in particijami nahaja na različnih strojih v gruči Kafka, ki ob pošiljanju ne usklajujejo transakcij. V času tega pisanja je bilo opravljenega nekaj dela, da bi to omogočili s KIP-98.
  • Povežite branje enega sporočila iz ene teme s pošiljanjem drugega sporočila v drugo temo. Spet je Kafkova arhitektura odvisna od številnih neodvisnih strojev, ki delujejo kot eno vodilo, in tega se ne poskuša skriti. Na primer, ni komponent API, ki bi vam omogočile povezavo potrošnik и Proizvajalec v transakciji. V JMS to zagotavlja predmet Sessioniz katerih so ustvarjeni MessageProducers и MessageConsumers.

Če se ne moremo zanesti na transakcije, kako lahko zagotovimo semantiko, ki je bližja tistim, ki jih zagotavljajo tradicionalni sistemi za sporočanje?

Če obstaja možnost, da se potrošnikov odmik poveča, preden je sporočilo obdelano, na primer med zrušitvijo potrošnika, potem potrošnik ne more vedeti, ali je njegova skupina potrošnikov zgrešila sporočilo, ko ji je dodeljena particija. Ena od strategij je torej previjanje odmika na prejšnji položaj. Uporabniški API Kafka ponuja naslednje metode za to:

void seek(TopicPartition partition, long offset);
void seekToBeginning(Collection < TopicPartition > partitions);

Metoda išči() se lahko uporablja z metodo
offsetsForTimes(Zemljevid timestampsToSearch) za previjanje v stanje na določeni točki v preteklosti.

Implicitno uporaba tega pristopa pomeni, da je zelo verjetno, da bodo nekatera sporočila, ki so bila predhodno obdelana, ponovno prebrana in obdelana. Da bi se temu izognili, lahko uporabimo idempotentno branje, kot je opisano v 4. poglavju, da sledimo predhodno ogledanim sporočilom in odstranimo dvojnike.

Druga možnost je, da je vaša potrošniška koda preprosta, če je izguba sporočila ali podvajanje sprejemljivo. Ko pogledamo primere uporabe, za katere se Kafka običajno uporablja, kot je obravnava dogodkov v dnevniku, metrike, sledenje klikom itd., ugotovimo, da izguba posameznih sporočil verjetno ne bo imela pomembnega vpliva na okoliške aplikacije. V takih primerih so privzete vrednosti povsem sprejemljive. Po drugi strani, če mora vaša aplikacija pošiljati plačila, morate skrbno poskrbeti za vsako posamezno sporočilo. Vse se spusti v kontekst.

Osebna opažanja kažejo, da se z večanjem intenzivnosti sporočil vrednost vsakega posameznega sporočila zmanjšuje. Velika sporočila so običajno dragocena, če jih gledamo v združeni obliki.

Visoka dostopnost

Kafkin pristop k visoki razpoložljivosti se zelo razlikuje od pristopa ActiveMQ. Kafka je zasnovana okoli razširljivih grozdov, kjer vse instance posrednika prejemajo in distribuirajo sporočila hkrati.

Grozd Kafka je sestavljen iz več primerkov posrednika, ki se izvajajo na različnih strežnikih. Kafka je bil zasnovan za delovanje na običajni samostojni strojni opremi, kjer ima vsako vozlišče svoj namenski pomnilnik. Uporaba omrežno priključenega pomnilnika (SAN) ni priporočljiva, ker lahko več računalniških vozlišč tekmuje za čas.Ыe intervali shranjevanja in ustvarjajo konflikte.

Kafka je vedno vklopljen sistem. Mnogi veliki uporabniki Kafke nikoli ne zaprejo svojih gruč in programska oprema se vedno posodobi z zaporednim ponovnim zagonom. To je doseženo z zagotavljanjem združljivosti s prejšnjo različico za sporočila in interakcije med posredniki.

Posredniki, povezani v strežniško gručo Oskrbnik živalskega vrta, ki deluje kot register konfiguracijskih podatkov in se uporablja za usklajevanje vlog vsakega posrednika. Sam ZooKeeper je porazdeljen sistem, ki zagotavlja visoko razpoložljivost s podvajanjem informacij z vzpostavitvijo sklepčnost.

V osnovnem primeru je tema ustvarjena v gruči Kafka z naslednjimi lastnostmi:

  • Število particij. Kot smo že omenili, je natančna vrednost, uporabljena tukaj, odvisna od želene ravni vzporednega branja.
  • Faktor podvajanja (faktor) določa, koliko primerkov posrednika v gruči naj vsebuje dnevnike za to particijo.

Z uporabo ZooKeepers za usklajevanje poskuša Kafka pravično porazdeliti nove particije med posrednike v gruči. To naredi en primerek, ki deluje kot krmilnik.

Med izvajanjem za vsako particijo teme Krmilnik posredniku dodeliti vloge vodja (vodja, mojster, voditelj) in sledilci (sledilci, sužnji, podrejeni). Posrednik, ki deluje kot vodja te particije, je odgovoren za prejemanje vseh sporočil, ki mu jih pošljejo proizvajalci, in za distribucijo sporočil potrošnikom. Ko so sporočila poslana tematski particiji, so podvojena na vsa posredniška vozlišča, ki delujejo kot sledilci za to particijo. Pokliče se vsako vozlišče, ki vsebuje dnevnike za particijo replika. Posrednik lahko deluje kot vodja za nekatere particije in kot sledilec za druge.

Pokliče se sledilec, ki vsebuje vsa sporočila, ki jih ima vodja sinhronizirana replika (replika, ki je v sinhroniziranem stanju, in-sinhronizirana replika). Če posrednik, ki deluje kot vodilni za particijo, preneha delovati, lahko kateri koli posrednik, ki je posodobljen ali sinhroniziran za to particijo, prevzame vlogo vodilnega. To je neverjetno trajnostna zasnova.

Del konfiguracije proizvajalca je parameter acks, ki določa, koliko replik mora potrditi (potrditi) prejem sporočila, preden nit aplikacije nadaljuje s pošiljanjem: 0, 1 ali vse. Če je nastavljeno na vse, potem ko je sporočilo prejeto, bo vodja poslal potrditev nazaj proizvajalcu takoj, ko prejme potrditve (potrditev) zapisa iz več iztočnic (vključno z njim samim), ki jih določa nastavitev teme min.insync.replicas (privzeto 1). Če sporočila ni mogoče uspešno podvojiti, bo proizvajalec vrgel izjemo aplikacije (NotEnoughReplicas ali NotEnoughReplicasAfterAppend).

Tipična konfiguracija ustvari temo s faktorjem podvajanja 3 (1 vodja, 2 sledilca na particijo) in parametrom min.insync.replicas je nastavljeno na 2. V tem primeru bo gruča enemu od posrednikov, ki upravljajo particijo tem, omogočila, da ne deluje, ne da bi to vplivalo na odjemalske aplikacije.

To nas pripelje nazaj k že znanemu kompromisu med zmogljivostjo in zanesljivostjo. Replikacija se zgodi na račun dodatnega čakanja na potrditve (priznanja) sledilcev. Ker pa teče vzporedno, ima replikacija na vsaj tri vozlišča enako zmogljivost kot dve (če ne upoštevamo povečane uporabe pasovne širine omrežja).

Z uporabo te sheme podvajanja se Kafka spretno izogne ​​potrebi po fizičnem zapisovanju vsakega sporočila na disk z operacijo sinhronizacija(). Vsako sporočilo, ki ga pošlje proizvajalec, bo zapisano v dnevnik particije, toda kot je razloženo v 2. poglavju, se pisanje v datoteko na začetku izvaja v medpomnilniku operacijskega sistema. Če je to sporočilo podvojeno v drug primerek Kafke in je v njegovem pomnilniku, izguba vodila ne pomeni, da je bilo sporočilo samo izgubljeno – lahko ga prevzame sinhronizirana replika.
Zavrnitev izvedbe operacije sinhronizacija() pomeni, da lahko Kafka sprejema sporočila tako hitro, kot jih lahko zapisuje v spomin. Nasprotno, dlje kot se lahko izogibate izpraznjevanju pomnilnika na disk, tem bolje. Iz tega razloga ni neobičajno, da posrednikom Kafka dodelijo 64 GB ali več pomnilnika. Ta uporaba pomnilnika pomeni, da lahko en primerek Kafke zlahka deluje s hitrostjo, ki je večtisočkrat hitrejša od tradicionalnega posrednika sporočil.

Kafko je mogoče konfigurirati tudi za uporabo operacije sinhronizacija() na pakete sporočil. Ker je vse v Kafki usmerjeno k paketom, dejansko deluje precej dobro za številne primere uporabe in je uporabno orodje za uporabnike, ki potrebujejo zelo močna jamstva. Velik del čiste zmogljivosti Kafke izhaja iz sporočil, ki so poslana posredniku kot paketi in ta sporočila posrednik prebere v zaporednih blokih z uporabo ničelna kopija operacije (operacije, med katerimi se ne izvaja naloga kopiranja podatkov iz enega pomnilniškega območja v drugega). Slednje pomeni veliko povečanje zmogljivosti in virov ter je možno le z uporabo osnovne podatkovne strukture dnevnika, ki definira particijsko shemo.

V gruči Kafka je mogoča veliko boljša zmogljivost kot z enim posrednikom Kafka, ker se lahko particije tem razširijo na veliko ločenih strojev.

Rezultati

V tem poglavju smo preučili, kako arhitektura Kafka na novo predstavlja odnos med strankami in posredniki, da bi zagotovila neverjetno robusten cevovod za sporočanje s prepustnostjo, ki je večkrat večja od pretoka običajnega posrednika sporočil. Razpravljali smo o funkcionalnosti, ki jo uporablja za doseganje tega, in si na kratko ogledali arhitekturo aplikacij, ki zagotavljajo to funkcionalnost. V naslednjem poglavju si bomo ogledali pogoste težave, ki jih morajo rešiti aplikacije, ki temeljijo na sporočanju, in razpravljali o strategijah za njihovo reševanje. Poglavje bomo zaključili z opisom, kako na splošno govoriti o tehnologijah sporočanja, da boste lahko ocenili njihovo primernost za vaše primere uporabe.

Prejšnji prevedeni del: Razumevanje posrednikov sporočil. Učenje mehanike sporočanja z ActiveMQ in Kafko. Poglavje 1

Prevod narejen: tele.gg/srednja_java

Se nadaljuje ...

V anketi lahko sodelujejo samo registrirani uporabniki. Prijaviti se, prosim.

Se Kafka uporablja v vaši organizaciji?

  • Da

  • Št

  • Prej uporabljen, zdaj ne

  • Načrtujemo uporabo

Glasovalo je 38 uporabnikov. 8 uporabnikov se je vzdržalo.

Vir: www.habr.com

Dodaj komentar