Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka

Nastavak prijevoda male knjige:
Razumijevanje brokera poruka
autor: Jakub Korab, izdavač: O'Reilly Media, Inc., datum izdanja: lipanj 2017., ISBN: 9781492049296.

Prethodni prevedeni dio: Razumijevanje posrednika poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. 1. poglavlje Uvod

POGLAVLJE 3

Kafka

Kafku je razvio LinkedIn kako bi se zaobišla neka ograničenja tradicionalnih brokera poruka i izbjeglo postavljanje više brokera poruka za različite interakcije od točke do točke, što je opisano u ovoj knjizi pod "Skaliranje i širenje" na stranici 28. Slučajevi korištenja LinkedIn se u velikoj mjeri oslanjao na jednosmjerno unošenje vrlo velikih količina podataka, kao što su klikovi na stranice i zapisnici pristupa, dok je još uvijek dopuštao da te podatke koristi više sustava bez utjecaja na produktivnost proizvođača ili drugih potrošača. Zapravo, razlog zašto Kafka postoji je da dobije arhitekturu za slanje poruka kakvu opisuje Universal Data Pipeline.

S obzirom na ovaj krajnji cilj, prirodno su se pojavili i drugi zahtjevi. Kafka bi trebao:

  • Budite izuzetno brzi
  • Omogućite veću propusnost pri radu s porukama
  • Podržava modele Publisher-Subscriber i Point-to-Point
  • Ne usporavajte s dodavanjem potrošača. Na primjer, performanse i reda i teme u ActiveMQ-u opadaju kako raste broj korisnika na odredištu.
  • Biti horizontalno skalabilan; ako jedan broker koji ustraje u porukama to može učiniti samo pri maksimalnoj brzini diska, onda ima smisla ići dalje od jedne instance brokera kako bi se povećala izvedba
  • Ograničite pristup pohranjivanju i ponovnom dohvaćanju poruka

Kako bi sve to postigao, Kafka je usvojio arhitekturu koja je redefinirala uloge i odgovornosti klijenata i posrednika za slanje poruka. JMS model je vrlo orijentiran na brokera, gdje je broker odgovoran za distribuciju poruka, a klijenti moraju brinuti samo o slanju i primanju poruka. Kafka je, s druge strane, usmjeren na klijenta, pri čemu klijent preuzima mnoge značajke tradicionalnog brokera, kao što je pravedna distribucija relevantnih poruka potrošačima, u zamjenu za iznimno brzog i skalabilnog brokera. Za ljude koji su radili s tradicionalnim sustavima slanja poruka, rad s Kafkom zahtijeva temeljnu promjenu mišljenja.
Ovaj inženjerski smjer doveo je do stvaranja infrastrukture za razmjenu poruka koja je sposobna povećati propusnost za mnogo redova veličine u usporedbi s konvencionalnim brokerom. Kao što ćemo vidjeti, ovaj pristup dolazi s kompromisima, što znači da Kafka nije prikladan za određene vrste radnih opterećenja i instaliranog softvera.

Objedinjeni model odredišta

Kako bi ispunio gore opisane zahtjeve, Kafka je kombinirao objavljivanje-pretplatu i slanje poruka od točke do točke pod jednom vrstom odredišta − tema. Ovo je zbunjujuće za ljude koji su radili sa sustavima za razmjenu poruka, gdje se riječ "tema" odnosi na mehanizam emitiranja iz kojeg (iz teme) čitanje nije trajno. Kafkine teme treba smatrati tipom hibridnog odredišta, kako je definirano u uvodu ove knjige.

U ostatku ovog poglavlja, osim ako izričito ne navedemo drugačije, pojam "tema" odnosit će se na Kafkinu temu.

Da bismo u potpunosti razumjeli kako se teme ponašaju i koja jamstva daju, prvo moramo pogledati kako su implementirane u Kafki.
Svaka tema u Kafki ima svoj dnevnik.
Proizvođači koji šalju poruke Kafki pišu u ovaj dnevnik, a potrošači čitaju iz dnevnika pomoću pokazivača koji se stalno pomiču prema naprijed. Kafka povremeno briše najstarije dijelove dnevnika, bez obzira jesu li poruke u tim dijelovima pročitane ili ne. Središnji dio Kafkinog dizajna je da brokera nije briga jesu li poruke pročitane ili ne - to je odgovornost klijenta.

Izrazi "log" i "pokazivač" ne pojavljuju se u Kafkina dokumentacija. Ovi dobro poznati pojmovi ovdje se koriste za lakše razumijevanje.

Ovaj model je potpuno drugačiji od ActiveMQ-a, gdje se poruke iz svih redova spremaju u isti zapisnik, a broker označava poruke kao izbrisane nakon što su pročitane.
Kopajmo sada malo dublje i pogledajmo dnevnik teme detaljnije.
Kafkin dnevnik sastoji se od nekoliko odjeljaka (Slika 3-1). Kafka jamči strogi poredak u svakoj particiji. To znači da će poruke napisane u particiji određenim redoslijedom biti pročitane istim redoslijedom. Svaka particija implementirana je kao pokretna datoteka dnevnika koja sadrži podskup (podskup) svih poruka koje su proizvođači poslali na temu. Stvorena tema prema zadanim postavkama sadrži jednu particiju. Ideja o pregradama središnja je Kafkina ideja za horizontalno skaliranje.

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-1. Kafkine pregrade

Kada producent pošalje poruku Kafkinoj temi, on odlučuje kojoj će particiji poslati poruku. Kasnije ćemo to detaljnije pogledati.

Čitanje poruka

Klijent koji želi čitati poruke upravlja imenovanim pokazivačem pozvanim skupina potrošača, što ukazuje na pomaknuti poruke u particiji. Pomak je inkrementalni položaj koji počinje od 0 na početku particije. Ova potrošačka grupa, navedena u API-ju putem korisnički definiranog group_id-a, odgovara jedan logički potrošač ili sustav.

Većina sustava za razmjenu poruka čita podatke s odredišta koristeći više instanci i niti za paralelnu obradu poruka. Stoga će obično postojati mnogo instanci potrošača koji dijele istu skupinu potrošača.

Problem čitanja može se predstaviti na sljedeći način:

  • Tema ima više odjeljaka
  • Više grupa potrošača može koristiti temu u isto vrijeme
  • Skupina potrošača može imati više zasebnih instanci

Ovo je netrivijalan problem mnogo-prema-više. Da bismo razumjeli kako Kafka upravlja odnosima između potrošačkih skupina, potrošačkih instanci i podjela, pogledajmo niz postupno složenijih scenarija čitanja.

Potrošači i skupine potrošača

Uzmimo kao početnu točku temu s jednom particijom (Slika 3-2).

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-2. Potrošač čita s particije

Kada se potrošačka instanca poveže sa svojim vlastitim group_id na ovu temu, dodjeljuje joj se particija za čitanje i pomak u toj particiji. Položaj ovog pomaka konfiguriran je u klijentu kao pokazivač na najnoviji položaj (najnovija poruka) ili najraniji položaj (najstarija poruka). Potrošač zahtijeva (anketira) poruke iz teme, što uzrokuje njihovo uzastopno čitanje iz dnevnika.
Položaj pomaka redovito se vraća Kafki i pohranjuje kao poruke u internoj temi _potrošački_pomaci. Pročitane poruke i dalje se ne brišu, za razliku od običnog posrednika, a klijent može premotati pomak kako bi ponovno obradio već pregledane poruke.

Kada se drugi logički potrošač poveže koristeći drugačiji group_id, on upravlja drugim pokazivačem koji je neovisan o prvom (Slika 3-3). Stoga se Kafkina tema ponaša kao red u kojem postoji jedan korisnik i kao normalna tema za objavljivanje-pretplatu (pub-sub) na koju se pretplaćuje više korisnika, uz dodatnu pogodnost da se sve poruke pohranjuju i mogu se obraditi više puta.

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-3. Dva potrošača u različitim skupinama potrošača čitaju s iste particije

Potrošači u skupini potrošača

Kada jedna potrošačka instanca čita podatke s particije, ima punu kontrolu nad pokazivačem i obrađuje poruke kao što je opisano u prethodnom odjeljku.
Ako je nekoliko instanci potrošača povezano s istim group_id na temu s jednom particijom, tada će instanca koja se zadnja povezala dobiti kontrolu nad pokazivačem i od tog trenutka će primati sve poruke (Slika 3-4).

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-4. Dva potrošača u istoj skupini potrošača čitaju iz iste particije

Ovaj način obrade, u kojem broj instanci potrošača premašuje broj particija, može se smatrati nekom vrstom ekskluzivnog potrošača. Ovo može biti korisno ako vam je potrebno "aktivno-pasivno" (ili "vruće-toplo") grupiranje instanci potrošača, iako je paralelno pokretanje više potrošača ("aktivno-aktivno" ili "vruće-vruće") mnogo tipičnije od potrošači.U pripravnosti.

Ovo gore opisano ponašanje distribucije poruka može biti iznenađujuće u usporedbi s načinom na koji se ponaša normalan JMS red čekanja. U ovom modelu, poruke poslane u red čekanja bit će ravnomjerno raspoređene između dva potrošača.

Najčešće, kada stvaramo višestruke instance potrošača, to radimo ili kako bismo paralelno obrađivali poruke, ili kako bismo povećali brzinu čitanja, ili kako bismo povećali stabilnost procesa čitanja. Budući da samo jedna potrošačka instanca može istovremeno čitati podatke s particije, kako se to postiže u Kafki?

Jedan od načina da to učinite je korištenje jedne potrošačke instance za čitanje svih poruka i njihovo prosljeđivanje skupu niti. Iako ovaj pristup povećava propusnost obrade, on povećava složenost potrošačke logike i ne čini ništa za povećanje robusnosti sustava za čitanje. Ako jedan primjerak potrošača padne zbog nestanka struje ili sličnog događaja, tada se oduzimanje zaustavlja.

Kanonski način rješavanja ovog problema kod Kafke je korištenje bОviše particija.

Particioniranje

Particije su glavni mehanizam za paralelno čitanje i skaliranje teme izvan propusnosti jedne brokerske instance. Da bismo ovo bolje razumjeli, razmotrimo situaciju u kojoj postoji tema s dvije particije i jedan korisnik se pretplatio na tu temu (Slika 3-5).

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-5. Jedan potrošač čita s više particija

U ovom scenariju potrošač dobiva kontrolu nad pokazivačima koji odgovaraju njegovom group_id-u u obje particije i počinje čitati poruke s obje particije.
Kada se ovoj temi doda dodatni potrošač za isti group_id, Kafka premješta jednu od particija s prvog na drugi potrošač. Nakon toga, svaka instanca potrošača će čitati iz jedne particije teme (Slika 3-6).

Kako biste osigurali da se poruke paralelno obrađuju u 20 niti, potrebno vam je najmanje 20 particija. Ako ima manje particija, ostat ćete s potrošačima koji nemaju na čemu raditi, kao što je ranije opisano u raspravi o isključivim potrošačima.

Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 3. Kafka
Slika 3-6. Dva potrošača u istoj skupini potrošača čitaju s različitih particija

Ova shema uvelike smanjuje složenost Kafka brokera u usporedbi s distribucijom poruka koja je potrebna za održavanje JMS reda. Ovdje ne morate brinuti o sljedećim točkama:

  • Koji potrošač treba primiti sljedeću poruku, na temelju kružne dodjele, trenutnog kapaciteta međuspremnika za prethodno dohvaćanje ili prethodnih poruka (kao za JMS grupe poruka).
  • Koje se poruke šalju kojim potrošačima i treba li ih ponovno dostaviti u slučaju kvara.

Sve što Kafka broker treba učiniti je proslijediti poruke potrošaču uzastopno kada ih ovaj zatraži.

Međutim, zahtjevi za paraleliziranjem lekture i ponovnog slanja neuspjelih poruka ne nestaju - odgovornost za njih jednostavno prelazi s brokera na klijenta. To znači da ih morate uzeti u obzir u svom kodu.

Slanje poruka

Odgovornost je proizvođača te poruke da odluči kojoj će se particiji poslati poruka. Da bismo razumjeli mehanizam kojim se to radi, prvo moramo razmotriti što točno šaljemo.

Dok u JMS-u koristimo strukturu poruke s metapodacima (zaglavlja i svojstva) i tijelom koje sadrži sadržaj (payload), u Kafki je poruka par "ključ-vrijednost". Korisni teret poruke šalje se kao vrijednost. Ključ se, s druge strane, uglavnom koristi za particioniranje i mora sadržavati specifičan ključ poslovne logikestaviti povezane poruke u istu particiju.

U 2. poglavlju raspravljali smo o scenariju online klađenja u kojem povezani događaji moraju biti obrađeni redom od strane jednog korisnika:

  1. Korisnički račun je konfiguriran.
  2. Novac se uplaćuje na račun.
  3. Sklapa se oklada koja povlači novac s računa.

Ako je svaki događaj poruka objavljena u temi, onda bi prirodni ključ bio ID računa.
Kada se poruka pošalje pomoću Kafka Producer API-ja, prosljeđuje se particijskoj funkciji koja, s obzirom na poruku i trenutno stanje Kafka klastera, vraća ID particije na koju treba poslati poruku. Ova je značajka implementirana u Javi putem sučelja Partitioner.

Ovo sučelje izgleda ovako:

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

Implementacija particionera koristi zadani algoritam raspršivanja opće namjene preko ključa za određivanje particije ili kružni postupak ako ključ nije naveden. Ova zadana vrijednost dobro funkcionira u većini slučajeva. Međutim, u budućnosti ćete htjeti napisati svoje.

Pisanje vlastite strategije particioniranja

Pogledajmo primjer u kojem želite poslati metapodatke zajedno s sadržajem poruke. Korisni teret u našem primjeru je instrukcija za uplatu na račun igre. Instrukcija je nešto za što želimo da bude zajamčeno da se neće mijenjati prilikom prijenosa i želimo biti sigurni da samo vjerodostojni uzvodni sustav može pokrenuti tu instrukciju. U ovom slučaju, sustavi slanja i primanja slažu se oko upotrebe potpisa za provjeru autentičnosti poruke.
U normalnom JMS-u jednostavno definiramo svojstvo "potpis poruke" i dodamo ga poruci. Međutim, Kafka nam ne daje mehanizam za prosljeđivanje metapodataka, samo ključ i vrijednost.

Budući da je vrijednost korisni teret bankovnog prijenosa čiji integritet želimo sačuvati, nemamo izbora nego definirati strukturu podataka koja će se koristiti u ključu. Pod pretpostavkom da nam je potreban ID računa za particioniranje, budući da se sve poruke povezane s računom moraju redom obrađivati, doći ćemo do sljedeće JSON strukture:

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

Budući da će vrijednost potpisa varirati ovisno o nosivosti, zadana strategija raspršivanja sučelja Particionera neće pouzdano grupirati povezane poruke. Stoga ćemo morati napisati vlastitu strategiju koja će analizirati ovaj ključ i particionirati vrijednost accountId.

Kafka uključuje kontrolne zbrojeve za otkrivanje oštećenja poruka u trgovini i ima cijeli skup sigurnosnih značajki. Unatoč tome, ponekad se pojavljuju zahtjevi specifični za industriju, kao što je gore navedeni.

Korisnička strategija particioniranja mora osigurati da sve povezane poruke završe u istoj particiji. Iako se ovo čini jednostavnim, zahtjev može biti kompliciran zbog važnosti redoslijeda povezanih poruka i koliko je fiksan broj particija u temi.

Broj particija u temi može se mijenjati tijekom vremena, budući da se mogu dodati ako promet premaši početna očekivanja. Stoga se ključevi poruka mogu povezati s particijom na koju su izvorno poslani, implicirajući dio stanja koji će se dijeliti između instanci proizvođača.

Drugi faktor koji treba uzeti u obzir je ravnomjerna distribucija poruka po particijama. Tipično, ključevi nisu ravnomjerno raspoređeni po porukama, a hash funkcije ne jamče pravednu distribuciju poruka za mali skup ključeva.
Važno je imati na umu da, kako god odlučite podijeliti poruke, sam separator možda ćete trebati ponovno upotrijebiti.

Razmotrite zahtjev za repliciranjem podataka između Kafka klastera na različitim geografskim lokacijama. U tu svrhu, Kafka dolazi s alatom naredbenog retka pod nazivom MirrorMaker, koji se koristi za čitanje poruka iz jednog klastera i njihov prijenos u drugi.

MirrorMaker mora razumjeti ključeve replicirane teme kako bi održao relativni poredak između poruka prilikom replikacije između klastera, budući da broj particija za tu temu možda neće biti isti u dva klastera.

Prilagođene strategije particioniranja relativno su rijetke jer zadano raspršivanje ili kružno funkcioniranje dobro funkcionira u većini scenarija. Međutim, ako su vam potrebna jaka jamstva za naručivanje ili trebate izvući metapodatke iz korisnih podataka, onda je particioniranje nešto čemu biste trebali pobliže pogledati.

Prednosti skalabilnosti i izvedbe Kafke proizlaze iz prebacivanja dijela odgovornosti tradicionalnog brokera na klijenta. U tom slučaju donosi se odluka o distribuciji potencijalno povezanih poruka među nekoliko potrošača koji rade paralelno.

JMS brokeri također se moraju nositi s takvim zahtjevima. Zanimljivo, mehanizam za slanje povezanih poruka istom korisniku, implementiran kroz JMS Message Groups (varijacija strategije ljepljivog balansiranja opterećenja (SLB)), također zahtijeva od pošiljatelja da označi poruke kao povezane. U slučaju JMS-a, broker je odgovoran za slanje ove grupe povezanih poruka jednom potrošaču od mnogih i prijenos vlasništva nad grupom ako potrošač otpadne.

Ugovori proizvođača

Particioniranje nije jedino što treba uzeti u obzir prilikom slanja poruka. Pogledajmo send() metode klase Producer u Java API-ju:

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

Treba odmah primijetiti da obje metode vraćaju Future, što znači da se operacija slanja ne izvodi odmah. Rezultat je da se poruka (ProducerRecord) zapisuje u međuspremnik za slanje za svaku aktivnu particiju i šalje brokeru kao pozadinska nit u Kafka klijentskoj biblioteci. Iako ovo čini stvari nevjerojatno brzima, to znači da neiskusna aplikacija može izgubiti poruke ako se njezin proces zaustavi.

Kao i uvijek, postoji način da se operacija slanja učini pouzdanijom na uštrb izvedbe. Veličina ovog međuspremnika može se postaviti na 0, a nit aplikacije koja šalje bit će prisiljena čekati dok se prijenos poruke brokeru ne završi, kako slijedi:

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

Više o čitanju poruka

Čitanje poruka ima dodatne složenosti o kojima treba nagađati. Za razliku od JMS API-ja, koji može pokrenuti slušatelja poruka kao odgovor na poruku, potrošač Kafka samo ankete. Pogledajmo pobliže metodu anketa()koristi se za ovu svrhu:

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

Povratna vrijednost metode je struktura spremnika koja sadrži više objekata rekord potrošača iz potencijalno nekoliko particija. rekord potrošača je sam po sebi objekt nositelja za par ključ-vrijednost s pridruženim metapodacima, kao što je particija iz koje je izveden.

Kao što je objašnjeno u 2. poglavlju, moramo imati na umu što se događa s porukama nakon što su uspješno ili neuspješno obrađene, na primjer, ako klijent ne može obraditi poruku ili ako ona prekine. U JMS-u se to rješavalo putem načina potvrde. Broker će ili izbrisati uspješno obrađenu poruku ili ponovno isporučiti neobrađenu ili lažnu poruku (pod pretpostavkom da su korištene transakcije).
Kafka radi vrlo drugačije. Poruke se ne brišu u brokeru nakon lekture, a što se događa u slučaju kvara odgovornost je samog koda za lekturu.

Kao što smo rekli, grupa potrošača povezana je s pomakom u dnevniku. Pozicija dnevnika povezana s ovim pomakom odgovara sljedećoj poruci koja se izdaje kao odgovor anketa(). Točka u vremenu kada se ovaj pomak povećava je odlučujuća za čitanje.

Vraćajući se na model čitanja o kojem smo ranije govorili, obrada poruke sastoji se od tri faze:

  1. Dohvati poruku za čitanje.
  2. Obradite poruku.
  3. Potvrdite poruku.

Kafka potrošač dolazi s opcijom konfiguracije enable.auto.commit. Ovo je često korištena zadana postavka, kao što je uobičajeno s postavkama koje sadrže riječ "auto".

Prije Kafke 0.10, klijent koji koristi ovu opciju slao bi pomak zadnje pročitane poruke pri sljedećem pozivu anketa() nakon obrade. To je značilo da se sve poruke koje su već bile dohvaćene mogu ponovno obraditi ako ih je klijent već obradio, ali je neočekivano uništen prije poziva anketa(). Budući da broker ne čuva nikakvo stanje o tome koliko je puta poruka pročitana, sljedeći korisnik koji preuzme tu poruku neće znati da se dogodilo nešto loše. Ovo ponašanje bilo je pseudotransakcijsko. Pomak je počinjen samo ako je poruka uspješno obrađena, ali ako je klijent odustao, posrednik bi ponovno poslao istu poruku drugom klijentu. Ovo ponašanje je bilo u skladu s jamstvom isporuke poruke "barem jednom”.

U Kafki 0.10, kod klijenta je promijenjen tako da commit povremeno pokreće klijentska biblioteka, kako je konfigurirano auto.commit.interval.ms. Ovo ponašanje je negdje između JMS AUTO_ACKNOWLEDGE i DUPS_OK_ACKNOWLEDGE načina. Kada koristite autocommit, poruke se mogu predati bez obzira na to jesu li stvarno obrađene - to se može dogoditi u slučaju sporog korisnika. Ako potrošač prekine, poruke bi dohvatio sljedeći potrošač, počevši od dodijeljene pozicije, što bi moglo rezultirati propuštenom porukom. U ovom slučaju Kafka nije izgubio poruke, samo ih kod za čitanje nije obradio.

Ovaj način ima isto obećanje kao u verziji 0.9: poruke se mogu obraditi, ali ako ne uspije, pomak se možda neće izvršiti, što može uzrokovati udvostručenje isporuke. Što više poruka dohvatite prilikom izvođenja anketa(), više ovaj problem.

Kao što je objašnjeno u “Čitanje poruka iz reda” na stranici 21, ne postoji takva stvar kao što je jednokratna isporuka poruke u sustavu za razmjenu poruka kada se uzmu u obzir načini kvara.

Kod Kafke postoje dva načina da se izvrši (commit) ofset (offset): automatski i ručno. U oba slučaja, poruke se mogu obraditi više puta ako je poruka obrađena, ali nije uspjela prije predaje. Također možete odlučiti da se poruka uopće ne obrađuje ako se commit dogodio u pozadini i vaš kod je dovršen prije nego što se mogao obraditi (možda u Kafki 0.9 i ranijim verzijama).

Postavljanjem parametra možete upravljati postupkom ručne predaje pomaka u Kafka korisničkom API-ju enable.auto.commit na false i eksplicitno pozivanje jedne od sljedećih metoda:

void commitSync();
void commitAsync();

Ako želite obraditi poruku "barem jednom", morate izvršiti pomak ručno s commitSync()izvršavanjem ove naredbe odmah nakon obrade poruka.

Ove metode ne dopuštaju potvrdu prijema poruka prije nego što se obrade, ali ne čine ništa kako bi eliminirale potencijalna kašnjenja u obradi, a daju dojam da su transakcijske. Kod Kafke nema transakcija. Klijent nema mogućnost sljedećeg:

  • Automatski vrati lažnu poruku. Potrošači sami moraju rješavati iznimke koje proizlaze iz problematičnih korisnih opterećenja i ispada u pozadini, jer se ne mogu osloniti na brokera da će ponovno dostaviti poruke.
  • Pošaljite poruke na više tema u jednoj atomskoj operaciji. Kao što ćemo uskoro vidjeti, kontrola nad različitim temama i particijama može se nalaziti na različitim strojevima u Kafka klasteru koji ne koordiniraju transakcije kada se pošalju. U vrijeme pisanja ovog teksta učinjeno je nešto kako bi se to omogućilo s KIP-98.
  • Povežite čitanje jedne poruke iz jedne teme sa slanjem druge poruke u drugu temu. Opet, Kafkina arhitektura ovisi o mnogim neovisnim strojevima koji rade kao jedna sabirnica i to se ne pokušava sakriti. Na primjer, ne postoje API komponente koje bi vam omogućile povezivanje potrošač и proizvođač u transakciji. U JMS-u to osigurava objekt Sjednicaod kojih se stvaraju MessageProducers и Potrošači poruka.

Ako se ne možemo osloniti na transakcije, kako možemo pružiti semantiku bližu onoj koju pružaju tradicionalni sustavi slanja poruka?

Ako postoji mogućnost da se pomak potrošača može povećati prije nego što je poruka obrađena, kao što je tijekom pada potrošača, tada potrošač nema načina znati je li njegova potrošačka grupa propustila poruku kada mu je dodijeljena particija. Dakle, jedna strategija je premotavanje pomaka na prethodnu poziciju. Kafka API za potrošače nudi sljedeće metode za to:

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

način tražiti() može se koristiti s metodom
offsetsForTimes(Mapa timestampsToSearch) premotati u stanje u nekoj određenoj točki u prošlosti.

Implicitno, korištenje ovog pristupa znači da je vrlo vjerojatno da će neke poruke koje su prethodno obrađene biti ponovno pročitane i obrađene. Da bismo to izbjegli, možemo koristiti idempotentno čitanje, kao što je opisano u poglavlju 4, da pratimo prethodno pregledane poruke i eliminiramo duplikate.

Alternativno, vaš korisnički kod može biti jednostavan, sve dok je gubitak ili dupliciranje poruke prihvatljivo. Kada uzmemo u obzir slučajeve upotrebe za koje se Kafka obično koristi, kao što je rukovanje događajima dnevnika, metrika, praćenje klikova itd., razumijemo da gubitak pojedinačnih poruka vjerojatno neće imati značajan utjecaj na okolne aplikacije. U takvim slučajevima, zadane vrijednosti su savršeno prihvatljive. S druge strane, ako vaša aplikacija treba slati uplate, morate pažljivo voditi računa o svakoj pojedinoj poruci. Sve se svodi na kontekst.

Osobna zapažanja pokazuju da s povećanjem intenziteta poruka vrijednost svake pojedine poruke opada. Velike poruke imaju tendenciju da budu vrijedne kada se gledaju u skupnom obliku.

Visoka dostupnost

Kafkin pristup visokoj dostupnosti jako se razlikuje od ActiveMQ pristupa. Kafka je dizajniran oko skaliranih klastera gdje sve brokerske instance primaju i distribuiraju poruke u isto vrijeme.

Kafka klaster sastoji se od više brokerskih instanci koje rade na različitim poslužiteljima. Kafka je dizajniran za rad na običnom samostalnom hardveru, gdje svaki čvor ima vlastitu namjensku pohranu. Korištenje mrežne pohrane (SAN) se ne preporučuje jer se više računalnih čvorova može natjecati za vrijeme.Ыe intervale skladištenja i stvoriti sukobe.

Kafka je uvijek uključeno sustav. Mnogi veliki Kafka korisnici nikada ne isključuju svoje klastere i softver se uvijek ažurira sekvencijalnim ponovnim pokretanjem. To se postiže jamčenjem kompatibilnosti s prethodnom verzijom za poruke i interakcije između brokera.

Brokeri spojeni na klaster poslužitelja Čuvar zoo vrta, koji djeluje kao registar konfiguracijskih podataka i koristi se za koordinaciju uloga svakog posrednika. Sam ZooKeeper je distribuirani sustav koji pruža visoku dostupnost kroz replikaciju informacija uspostavom kvorum.

U osnovnom slučaju, tema se kreira u Kafka klasteru sa sljedećim svojstvima:

  • Broj particija. Kao što je ranije objašnjeno, točna vrijednost koja se ovdje koristi ovisi o željenoj razini paralelnog čitanja.
  • Faktor replikacije (faktor) određuje koliko brokerskih instanci u klasteru treba sadržavati zapisnike za ovu particiju.

Koristeći ZooKeepers za koordinaciju, Kafka pokušava pravedno raspodijeliti nove particije među brokerima u klasteru. To radi jedna instanca koja djeluje kao kontroler.

Tijekom izvođenja za svaku particiju teme Kontroler dodijeliti uloge brokeru vođa (voditelj, majstor, voditelj) i sljedbenici (sljedbenici, robovi, podređeni). Posrednik, koji djeluje kao voditelj ove podjele, odgovoran je za primanje svih poruka koje mu šalju proizvođači i distribuciju poruka potrošačima. Kada se poruke pošalju na particiju teme, one se repliciraju na sve brokerske čvorove koji djeluju kao sljedbenici za tu particiju. Poziva se svaki čvor koji sadrži zapise za particiju replika. Broker može djelovati kao vođa za neke particije i kao sljedbenik za druge.

Poziva se sljedbenik koji sadrži sve poruke koje drži vođa sinkronizirana replika (replika koja je u sinkroniziranom stanju, in-sync replika). Ako posrednik koji djeluje kao voditelj za particiju padne, bilo koji posrednik koji je ažuran ili sinkroniziran za tu particiju može preuzeti ulogu voditelja. To je nevjerojatno održiv dizajn.

Dio konfiguracije proizvođača je parametar acks, koji određuje koliko replika mora potvrditi (potvrditi) primitak poruke prije nego što aplikacijska nit nastavi slati: 0, 1 ili sve. Ako je postavljeno na svi, tada kada se primi poruka, voditelj će poslati potvrdu natrag proizvođaču čim primi potvrde (potvrde) zapisa iz nekoliko znakova (uključujući njega) definiranih postavkom teme min.insync.replike (zadano 1). Ako se poruka ne može uspješno replicirati, proizvođač će izbaciti iznimku aplikacije (NotEnoughReplicas ili NotEnoughReplicasAfterAppend).

Tipična konfiguracija stvara temu s faktorom replikacije 3 (1 vođa, 2 sljedbenika po particiji) i parametrom min.insync.replike je postavljeno na 2. U ovom slučaju, klaster će omogućiti jednom od brokera koji upravljaju particijom teme da padne bez utjecaja na klijentske aplikacije.

Ovo nas vraća na već poznati kompromis između performansi i pouzdanosti. Replikacija se događa nauštrb dodatnog vremena čekanja za potvrde (potvrde) od pratitelja. Iako, budući da radi paralelno, replikacija na najmanje tri čvora ima istu izvedbu kao dva (ignorirajući povećanje upotrebe propusnosti mreže).

Koristeći ovu shemu replikacije, Kafka vješto izbjegava potrebu za fizičkim pisanjem svake poruke na disk operacijom sinkronizacija(). Svaka poruka koju pošalje proizvođač bit će zapisana u dnevnik particije, ali kao što je objašnjeno u 2. poglavlju, pisanje u datoteku prvo se vrši u međuspremniku operativnog sustava. Ako se ova poruka replicira na drugu Kafkinu instancu i nalazi se u njezinoj memoriji, gubitak voditelja ne znači da je sama poruka izgubljena - može je preuzeti sinkronizirana replika.
Odbijanje izvođenja operacije sinkronizacija() znači da Kafka može primati poruke onoliko brzo koliko ih može zapisati u memoriju. Obrnuto, što dulje možete izbjegavati ispiranje memorije na disk, to bolje. Iz tog razloga nije neuobičajeno da se Kafka brokerima dodijeli 64 GB ili više memorije. Ova upotreba memorije znači da se jedna Kafka instanca može lako pokrenuti brzinom koja je mnogo tisuća puta brža od tradicionalnog brokera poruka.

Kafka se također može konfigurirati za primjenu operacije sinkronizacija() na pakete poruka. Budući da je sve u Kafki orijentirano na pakete, zapravo radi prilično dobro za mnoge slučajeve upotrebe i koristan je alat za korisnike koji zahtijevaju vrlo jaka jamstva. Velik dio čiste izvedbe Kafke dolazi od poruka koje se šalju posredniku kao paketi i da se te poruke čitaju od posrednika u uzastopnim blokovima koristeći nulta kopija operacije (operacije tijekom kojih se ne izvršava zadatak kopiranja podataka iz jednog memorijskog područja u drugo). Potonje je velika izvedba i dobitak resursa i moguće je samo korištenjem temeljne strukture podataka dnevnika koja definira particijsku shemu.

Puno bolja izvedba moguća je u Kafka klasteru nego s jednim Kafka brokerom, jer se particije tema mogu proširiti na mnogo zasebnih strojeva.

Rezultati

U ovom poglavlju, pogledali smo kako Kafka arhitektura ponovno zamišlja odnos između klijenata i brokera kako bi pružila nevjerojatno robustan cjevovod za razmjenu poruka, s propusnošću mnogo puta većom od one kod konvencionalnog brokera za poruke. Razgovarali smo o funkcionalnosti koju koristi da bi to postigao i ukratko pogledali arhitekturu aplikacija koje pružaju tu funkcionalnost. U sljedećem poglavlju pogledat ćemo uobičajene probleme koje aplikacije temeljene na slanju poruka trebaju riješiti i raspravljati o strategijama za njihovo rješavanje. Završit ćemo poglavlje navodeći kako općenito govoriti o tehnologijama slanja poruka kako biste mogli procijeniti njihovu prikladnost za vaše slučajeve upotrebe.

Prethodni prevedeni dio: Razumijevanje brokera poruka. Učenje mehanike slanja poruka s ActiveMQ i Kafkom. Poglavlje 1

Prijevod završen: tele.gg/srednja_java

Da bi se nastavio ...

U anketi mogu sudjelovati samo registrirani korisnici. Prijaviti se, molim.

Koristi li se Kafka u vašoj organizaciji?

  • Da

  • Ne

  • Prije korišten, sada ne

  • Planiramo koristiti

Glasovalo je 38 korisnika. Suzdržano je bilo 8 korisnika.

Izvor: www.habr.com

Dodajte komentar