Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka

Pokračovanie prekladu útlej knižky:
Pochopenie sprostredkovateľov správ
autor: Jakub Korab, vydavateľ: O'Reilly Media, Inc., dátum vydania: jún 2017, ISBN: 9781492049296.

Predchádzajúca preložená časť: Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 1 Úvod

KAPITOLA 3

Kafka

Kafka bol vyvinutý spoločnosťou LinkedIn, aby obišiel niektoré z obmedzení tradičných sprostredkovateľov správ a nemusel nastavovať viacerých sprostredkovateľov správ pre rôzne interakcie point-to-point, čo je popísané v tejto knihe v časti „Zväčšenie a zmenšenie“ na strane 28. Prípady použitia LinkedIn sa vo veľkej miere spolieha na jednosmerné prijímanie veľmi veľkého množstva údajov, ako sú kliknutia na stránky a denníky prístupov, pričom stále umožňuje, aby tieto údaje používali viaceré systémy bez vplyvu na produktivitu výrobcov alebo iných spotrebiteľov. V skutočnosti dôvod, prečo Kafka existuje, je získať druh architektúry správ, ktorý popisuje Universal Data Pipeline.

Vzhľadom na tento konečný cieľ prirodzene vyvstali ďalšie požiadavky. Kafka by mal:

  • Buďte extrémne rýchly
  • Poskytnite väčšiu šírku pásma pri práci so správami
  • Podpora modelov Publisher-Subscriber a Point-to-Point
  • Nespomaľujte s pridávaním spotrebiteľov. Napríklad výkon frontu aj témy v ActiveMQ sa znižuje s rastúcim počtom spotrebiteľov v cieli.
  • Byť horizontálne škálovateľný; ak jeden maklér, ktorý uchováva správy, to môže robiť iba pri maximálnej rýchlosti disku, potom má zmysel ísť nad rámec jednej inštancie makléra, aby sa zvýšil výkon
  • Obmedzte prístup k ukladaniu a opätovnému získavaniu správ

Na dosiahnutie tohto všetkého prijal Kafka architektúru, ktorá nanovo definovala úlohy a zodpovednosti klientov a maklérov. Model JMS je veľmi orientovaný na makléra, kde maklér zodpovedá za distribúciu správ a klienti sa musia starať len o odosielanie a prijímanie správ. Kafka je na druhej strane orientovaný na klienta, pričom klient preberá mnohé z vlastností tradičného makléra, ako je spravodlivé rozdeľovanie relevantných správ spotrebiteľom, výmenou za mimoriadne rýchleho a škálovateľného makléra. Pre ľudí, ktorí pracovali s tradičnými systémami zasielania správ, si práca s Kafkom vyžaduje zásadnú zmenu myslenia.
Tento inžiniersky smer viedol k vytvoreniu infraštruktúry na odosielanie správ schopnej zvýšiť priepustnosť o mnoho rádov v porovnaní s konvenčným maklérom. Ako uvidíme, tento prístup prichádza s kompromismi, čo znamená, že Kafka nie je vhodný pre určité typy záťaže a nainštalovaný softvér.

Jednotný model destinácie

Na splnenie požiadaviek popísaných vyššie Kafka skombinoval publikovať-predplatiť a posielať správy z bodu do bodu pod jedným druhom miesta určenia − tému. Toto je mätúce pre ľudí, ktorí pracovali so systémami zasielania správ, kde slovo „téma“ označuje mechanizmus vysielania, z ktorého je čítanie (z témy) netrvanlivé. Kafkove témy by sa mali považovať za hybridný typ destinácie, ako je definované v úvode tejto knihy.

Pokiaľ nie je výslovne uvedené inak, vo zvyšku tejto kapitoly sa výraz „téma“ bude vzťahovať na Kafkovu tému.

Aby sme plne pochopili, ako sa témy správajú a aké záruky poskytujú, musíme sa najprv pozrieť na to, ako sú implementované v Kafke.
Každá téma v Kafkovi má svoj vlastný denník.
Výrobcovia, ktorí posielajú správy Kafkovi, zapisujú do tohto denníka a spotrebitelia z denníka čítajú pomocou ukazovateľov, ktoré sa neustále posúvajú vpred. Kafka pravidelne odstraňuje najstaršie časti denníka, či už boli správy v týchto častiach prečítané alebo nie. Ústrednou súčasťou Kafkovho dizajnu je, že maklérovi je jedno, či sa správy čítajú alebo nie – to je zodpovednosť klienta.

Výrazy „log“ a „ukazovateľ“ sa v ňom nevyskytujú Kafkovu dokumentáciu. Tieto dobre známe výrazy sú tu použité na uľahčenie porozumenia.

Tento model je úplne odlišný od ActiveMQ, kde sú správy zo všetkých frontov uložené v rovnakom protokole a broker po prečítaní označí správy ako vymazané.
Poďme sa teraz pohrabať trochu hlbšie a pozrieť sa na denník tém podrobnejšie.
Kafkov denník pozostáva z niekoľkých oddielov (Obrázok 3-1). Kafka garantuje prísne usporiadanie v každej priečke. To znamená, že správy zapísané do oddielu v určitom poradí sa budú čítať v rovnakom poradí. Každý oddiel je implementovaný ako rolovací protokolový súbor, ktorý obsahuje podmnožina (podmnožina) všetkých správ odoslaných k téme jej výrobcami. Vytvorená téma obsahuje štandardne jeden oddiel. Myšlienka oddielov je ústrednou myšlienkou Kafku pre horizontálne škálovanie.

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-1. Kafkove priečky

Keď producent pošle správu ku Kafkovej téme, rozhodne, ktorej partícii správu pošle. Na to sa pozrieme podrobnejšie neskôr.

Čítanie správ

Klient, ktorý chce čítať správy, spravuje pomenovaný ukazovateľ tzv skupina spotrebiteľov, ktorý poukazuje na offset správy v oddiele. Posun je prírastková pozícia, ktorá začína na 0 na začiatku oddielu. Táto skupina spotrebiteľov, na ktorú sa odkazuje v rozhraní API prostredníctvom používateľom definovaného group_id, zodpovedá jeden logický spotrebiteľ alebo systém.

Väčšina systémov na odosielanie správ číta údaje z miesta určenia pomocou viacerých inštancií a vlákien na spracovanie správ paralelne. Zvyčajne teda bude veľa inštancií spotrebiteľov zdieľať rovnakú skupinu spotrebiteľov.

Problém čítania možno znázorniť takto:

  • Téma má viacero oddielov
  • Tému môže používať viacero skupín spotrebiteľov súčasne
  • Skupina spotrebiteľov môže mať viacero samostatných inštancií

Toto je netriviálny problém typu many-to-many. Aby sme pochopili, ako Kafka rieši vzťahy medzi spotrebiteľskými skupinami, spotrebiteľskými inštanciami a oddielmi, pozrime sa na sériu postupne zložitejších scenárov čítania.

Spotrebitelia a skupiny spotrebiteľov

Zoberme si ako východiskový bod tému s jedným oddielom (Obrázok 3-2).

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-2. Spotrebiteľ číta z oddielu

Keď sa inštancia spotrebiteľa pripojí s vlastným group_id k tejto téme, priradí sa jej čítací oddiel a posun v tomto oddiele. Pozícia tohto posunu je konfigurovateľná v klientovi ako ukazovateľ na najnovšiu pozíciu (najnovšia správa) alebo najskoršiu pozíciu (najstaršia správa). Spotrebiteľ požaduje (hlasuje) správy z témy, čo spôsobí ich postupné prečítanie z denníka.
Offsetová pozícia sa pravidelne odosiela späť Kafkovi a ukladá sa ako správy v internej téme _consumer_offsets. Prečítané správy sa na rozdiel od bežného brokera stále nevymažú a klient môže posun pretočiť späť, aby znovu spracoval už prezreté správy.

Keď sa druhý logický spotrebiteľ pripojí pomocou iného group_id, spravuje druhý ukazovateľ, ktorý je nezávislý od prvého (Obrázok 3-3). Kafkova téma teda funguje ako rad, v ktorom je jeden spotrebiteľ, a ako bežná téma typu publikovať a odoberať (pub-sub), ktorú odoberá viacero spotrebiteľov, s ďalšou výhodou, že všetky správy sú uložené a môžu byť spracované viackrát.

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-3. Dvaja spotrebitelia v rôznych skupinách spotrebiteľov čítajú z rovnakého oddielu

Spotrebitelia v skupine spotrebiteľov

Keď jedna inštancia spotrebiteľa číta údaje z oddielu, má plnú kontrolu nad ukazovateľom a spracováva správy, ako je opísané v predchádzajúcej časti.
Ak bolo niekoľko inštancií spotrebiteľov pripojených s rovnakým group_id k téme s jedným oddielom, potom inštancia, ktorá sa pripojila ako posledná, získa kontrolu nad ukazovateľom a od tohto momentu bude dostávať všetky správy (Obrázok 3-4).

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-4. Dvaja spotrebitelia v rovnakej skupine spotrebiteľov čítajú z rovnakého oddielu

Tento spôsob spracovania, v ktorom počet inštancií spotrebiteľa prevyšuje počet oddielov, možno považovať za druh exkluzívneho spotrebiteľa. To môže byť užitočné, ak potrebujete „aktívne-pasívne“ (alebo „horúce-teplé“) klastrovanie inštancií vašich spotrebiteľov, hoci paralelné spustenie viacerých spotrebiteľov („aktívny-aktívny“ alebo „horúce-horúce“) je oveľa bežnejšie ako v pohotovostnom režime.

Toto správanie pri distribúcii správ opísané vyššie môže byť prekvapujúce v porovnaní s tým, ako sa správa normálny front JMS. V tomto modeli budú správy odoslané do frontu rovnomerne rozdelené medzi dvoch spotrebiteľov.

Najčastejšie, keď vytvárame viacero inštancií spotrebiteľov, robíme to buď preto, aby sme spracovávali správy paralelne, alebo aby sme zvýšili rýchlosť čítania alebo zvýšili stabilitu procesu čítania. Keďže iba jedna inštancia spotrebiteľa môže čítať údaje z oddielu naraz, ako sa to dosiahne v Kafke?

Jedným zo spôsobov, ako to urobiť, je použiť jednu inštanciu spotrebiteľa na čítanie všetkých správ a ich odovzdanie do oblasti vlákien. Zatiaľ čo tento prístup zvyšuje priepustnosť spracovania, zvyšuje zložitosť spotrebiteľskej logiky a nerobí nič pre zvýšenie robustnosti čítacieho systému. Ak jedna kópia spotrebiča vypadne z dôvodu výpadku napájania alebo podobnej udalosti, odčítanie sa zastaví.

Kanonický spôsob riešenia tohto problému u Kafku je použitie bОviac oddielov.

Rozdelenie

Oddiely sú hlavným mechanizmom na paralelizáciu čítania a škálovania témy nad rámec šírky pásma jednej inštancie makléra. Aby sme tomu lepšie porozumeli, uvažujme o situácii, keď existuje téma s dvoma oddielmi a jeden spotrebiteľ sa prihlási na odber tejto témy (Obrázok 3-5).

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-5. Jeden spotrebiteľ číta z viacerých oddielov

V tomto scenári dostane spotrebiteľ kontrolu nad ukazovateľmi zodpovedajúcimi jeho group_id v oboch oddieloch a začne čítať správy z oboch oddielov.
Keď sa k tejto téme pridá ďalší spotrebiteľ pre rovnaké group_id, Kafka prerozdelí jeden z oddielov z prvého na druhého spotrebiteľa. Potom bude každá inštancia spotrebiteľa čítať z jednej časti témy (Obrázok 3-6).

Ak chcete zabezpečiť, aby sa správy spracovávali paralelne v 20 vláknach, potrebujete aspoň 20 oblastí. Ak je oddielov menej, zostanú vám spotrebitelia, ktorí nemajú na čom pracovať, ako bolo opísané vyššie v diskusii o exkluzívnych spotrebiteľoch.

Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 3. Kafka
Obrázok 3-6. Dvaja spotrebitelia v rovnakej skupine spotrebiteľov čítajú z rôznych oddielov

Táto schéma výrazne znižuje zložitosť sprostredkovateľa Kafka v porovnaní s distribúciou správ potrebnou na udržiavanie frontu JMS. Tu sa nemusíte obávať nasledujúcich bodov:

  • Ktorý spotrebiteľ by mal dostať nasledujúcu správu na základe prideľovania medzi jednotlivými okruhmi, aktuálnej kapacity vyrovnávacích pamätí predbežného vyzdvihnutia alebo predchádzajúcich správ (ako v prípade skupín správ JMS).
  • Ktoré správy sa odosielajú ktorým spotrebiteľom a či by sa mali v prípade zlyhania znova doručiť.

Všetko, čo maklér Kafka musí urobiť, je postupne posielať správy spotrebiteľovi, keď o ne požiada.

Požiadavky na paralelizáciu korektúry a opätovného odosielania neúspešných správ však nezmiznú - zodpovednosť za ne jednoducho prechádza z makléra na klienta. To znamená, že musia byť zohľadnené vo vašom kóde.

Odosielanie správ

Je zodpovednosťou výrobcu tejto správy rozhodnúť, ktorému oddielu sa má správa poslať. Aby sme pochopili mechanizmus, ktorým sa to deje, musíme najprv zvážiť, čo presne vlastne posielame.

Zatiaľ čo v JMS používame štruktúru správy s metadátami (hlavičky a vlastnosti) a telom obsahujúcim užitočné zaťaženie (payload), v Kafke je správa pár „kľúč – hodnota“. Užitočné zaťaženie správy sa odošle ako hodnota. Kľúč sa na druhej strane používa hlavne na rozdelenie a musí obsahovať špecifický kľúč obchodnej logikyumiestniť súvisiace správy do rovnakej oblasti.

V kapitole 2 sme diskutovali o scenári online stávkovania, kde súvisiace udalosti musí spracovať v poradí jeden spotrebiteľ:

  1. Používateľský účet je nakonfigurovaný.
  2. Peniaze sú pripísané na účet.
  3. Uskutoční sa stávka, ktorá vyberie peniaze z účtu.

Ak je každá udalosť správou uverejnenou v téme, prirodzeným kľúčom by bolo ID účtu.
Keď sa správa odošle pomocou rozhrania Kafka Producer API, odošle sa do funkcie oddielu, ktorá vzhľadom na správu a aktuálny stav klastra Kafka vráti ID oddielu, do ktorého sa má správa odoslať. Táto funkcia je implementovaná v jazyku Java prostredníctvom rozhrania Partitioner.

Toto rozhranie vyzerá takto:

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

Implementácia Partitioner používa predvolený univerzálny hašovací algoritmus nad kľúčom na určenie oddielu alebo cyklickú obsluhu, ak nie je špecifikovaný žiadny kľúč. Táto predvolená hodnota funguje vo väčšine prípadov dobre. V budúcnosti však budete chcieť napísať svoj vlastný.

Napísanie vlastnej stratégie rozdelenia

Pozrime sa na príklad, kde chcete odoslať metadáta spolu s užitočným zaťažením správy. Užitočné zaťaženie v našom príklade je pokyn na vykonanie vkladu na herný účet. Inštrukcia je niečo, čo by sme chceli zaručiť, že sa pri prenose nezmení a chceme si byť istí, že túto inštrukciu môže iniciovať iba dôveryhodný nadradený systém. V tomto prípade sa odosielajúci a prijímajúci systém dohodnú na použití podpisu na overenie správy.
V bežnom JMS jednoducho definujeme vlastnosť „podpis správy“ a pridáme ju do správy. Kafka nám však neposkytuje mechanizmus na odovzdávanie metadát, iba kľúč a hodnotu.

Keďže hodnotou je bankový prevod, ktorého integritu chceme zachovať, nezostáva nám nič iné, ako definovať dátovú štruktúru, ktorú použijeme v kľúči. Za predpokladu, že na rozdelenie potrebujeme ID účtu, keďže všetky správy súvisiace s účtom musia byť spracované v poradí, prídeme s nasledujúcou štruktúrou JSON:

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

Pretože hodnota podpisu sa bude líšiť v závislosti od užitočného zaťaženia, predvolená stratégia hashovania rozhrania Partitioner nebude spoľahlivo zoskupovať súvisiace správy. Preto budeme musieť napísať vlastnú stratégiu, ktorá tento kľúč analyzuje a rozdelí hodnotu accountId.

Kafka obsahuje kontrolné súčty na detekciu poškodenia správ v obchode a má celú sadu bezpečnostných funkcií. Napriek tomu sa niekedy objavia požiadavky špecifické pre dané odvetvie, ako napríklad tá vyššie.

Stratégia delenia užívateľa musí zabezpečiť, aby všetky súvisiace správy skončili v rovnakom oddiele. Aj keď sa to zdá jednoduché, požiadavka môže byť komplikovaná dôležitosťou objednávania súvisiacich správ a pevným počtom oddielov v téme.

Počet oddielov v téme sa môže časom meniť, pretože môžu byť pridané, ak prevádzka prekročí pôvodné očakávania. Kľúče správ teda môžu byť spojené s oddielom, do ktorého boli pôvodne odoslané, čo znamená, že časť stavu sa má zdieľať medzi inštanciami výrobcu.

Ďalším faktorom, ktorý treba zvážiť, je rovnomerné rozloženie správ medzi oddielmi. Kľúče zvyčajne nie sú v správach rozdelené rovnomerne a hašovacie funkcie nezaručujú spravodlivé rozdelenie správ pre malú skupinu kľúčov.
Je dôležité si uvedomiť, že akokoľvek sa rozhodnete správy rozdeliť, možno bude potrebné znova použiť samotný oddeľovač.

Zvážte požiadavku na replikáciu údajov medzi klastrami Kafka v rôznych geografických lokalitách. Na tento účel prichádza Kafka s nástrojom príkazového riadka s názvom MirrorMaker, ktorý slúži na čítanie správ z jedného klastra a ich prenos do druhého.

MirrorMaker musí porozumieť kľúčom replikovanej témy, aby zachoval relatívne poradie medzi správami pri replikácii medzi klastrami, pretože počet oddielov pre túto tému nemusí byť v dvoch klastroch rovnaký.

Vlastné stratégie rozdeľovania sú relatívne zriedkavé, pretože predvolené hashovanie alebo kruhové spracovanie funguje dobre vo väčšine scenárov. Ak však požadujete silné záruky objednávania alebo potrebujete extrahovať metadáta z užitočných dát, potom by ste sa mali bližšie pozrieť na rozdelenie.

Škálovateľnosť a výkonnostné výhody Kafky pochádzajú z presunu niektorých zodpovedností tradičného makléra na klienta. V tomto prípade sa rozhodne o distribúcii potenciálne súvisiacich správ medzi niekoľkých paralelne pracujúcich spotrebiteľov.

S takými požiadavkami sa musia vyrovnať aj JMS brokeri. Je zaujímavé, že mechanizmus na odosielanie súvisiacich správ tomu istému spotrebiteľovi, implementovaný prostredníctvom skupín správ JMS (variácia stratégie lepkavého vyrovnávania záťaže (SLB)), tiež vyžaduje, aby odosielateľ označil správy ako súvisiace. V prípade JMS je sprostredkovateľ zodpovedný za odoslanie tejto skupiny súvisiacich správ jednému spotrebiteľovi z mnohých a za prevod vlastníctva skupiny, ak spotrebiteľ odpadne.

Dohody s výrobcom

Rozdelenie nie je jediná vec, ktorú je potrebné zvážiť pri odosielaní správ. Pozrime sa na metódy send() triedy Producer v Java API:

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

Okamžite treba poznamenať, že obe metódy vrátia Future, čo znamená, že operácia odoslania sa nevykoná okamžite. Výsledkom je, že správa (ProducerRecord) sa zapíše do odosielacej vyrovnávacej pamäte pre každý aktívny oddiel a odošle sa sprostredkovateľovi ako vlákno na pozadí v klientskej knižnici Kafka. Aj keď to robí veci neuveriteľne rýchlymi, znamená to, že neskúsená aplikácia môže stratiť správy, ak sa jej proces zastaví.

Ako vždy, existuje spôsob, ako zvýšiť spoľahlivosť odosielania na úkor výkonu. Veľkosť tejto vyrovnávacej pamäte môže byť nastavená na 0 a vlákno odosielajúcej aplikácie bude nútené čakať, kým sa nedokončí prenos správy sprostredkovateľovi, a to nasledovne:

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

Viac o čítaní správ

Čítanie správ má ďalšie zložitosti, o ktorých je potrebné špekulovať. Na rozdiel od JMS API, ktoré môže spustiť poslucháč správ ako odpoveď na správu, Spotrebiteľ Kafka len prieskumy. Pozrime sa bližšie na metódu anketa()používané na tento účel:

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

Návratovou hodnotou metódy je kontajnerová štruktúra obsahujúca viacero objektov spotrebiteľský záznam z potenciálne niekoľkých oddielov. spotrebiteľský záznam je samotný objekt držiteľa pre pár kľúč – hodnota s pridruženými metaúdajmi, ako je napríklad oddiel, z ktorého je odvodený.

Ako je uvedené v kapitole 2, musíme mať na pamäti, čo sa stane so správami po ich úspešnom alebo neúspešnom spracovaní, napríklad ak klient nie je schopný spracovať správu alebo ak sa preruší. V JMS sa to riešilo prostredníctvom režimu potvrdenia. Sprostredkovateľ buď vymaže úspešne spracovanú správu, alebo znova doručí nespracovanú alebo falošnú správu (za predpokladu, že boli použité transakcie).
Kafka funguje úplne inak. Správy sa v brokerovi po korektúre nevymažú a to, čo sa stane pri zlyhaní, je zodpovednosťou samotného kódu korektúry.

Ako sme už povedali, skupina spotrebiteľov je spojená s posunom v protokole. Pozícia denníka spojená s týmto posunom zodpovedá ďalšej správe, ktorá sa má vydať ako odpoveď anketa(). Pre čítanie je rozhodujúci okamih, kedy sa tento posun zvyšuje.

Ak sa vrátime k modelu čítania, o ktorom sme hovorili vyššie, spracovanie správ pozostáva z troch fáz:

  1. Získajte správu na prečítanie.
  2. Spracujte správu.
  3. Potvrďte správu.

Spotrebiteľ Kafka prichádza s možnosťou konfigurácie povoliť.auto.potvrdenie. Toto je často používané predvolené nastavenie, ktoré je bežné pri nastaveniach obsahujúcich slovo „auto“.

Pred verziou Kafka 0.10 klient využívajúci túto možnosť posielal offset poslednej prečítanej správy pri nasledujúcom hovore anketa() po spracovaní. To znamenalo, že všetky správy, ktoré už boli načítané, mohli byť znovu spracované, ak ich klient už spracoval, ale pred volaním boli neočakávane zničené anketa(). Pretože maklér neuchováva žiadny stav o tom, koľkokrát bola správa prečítaná, ďalší spotrebiteľ, ktorý túto správu získa, nebude vedieť, že sa stalo niečo zlé. Toto správanie bolo pseudotransakčné. Posun bol potvrdený iba vtedy, ak bola správa úspešne spracovaná, ale ak sa klient prerušil, maklér by znova poslal rovnakú správu inému klientovi. Toto správanie bolo v súlade so zárukou doručenia správy "aspoň raz".

V Kafka 0.10 bol klientsky kód zmenený tak, že odovzdanie je pravidelne spúšťané klientskou knižnicou, ako je nakonfigurované auto.commit.interval.ms. Toto správanie je niekde medzi režimami JMS AUTO_ACKNOWLEDGE a DUPS_OK_ACKNOWLEDGE. Pri použití automatického potvrdzovania môžu byť správy potvrdené bez ohľadu na to, či boli skutočne spracované - to sa môže stať v prípade pomalého spotrebiteľa. Ak by sa spotrebiteľ prerušil, správy by vyzdvihol ďalší spotrebiteľ, počnúc od potvrdenej pozície, čo by mohlo viesť k zmeškanej správe. V tomto prípade Kafka správy nestratil, čítací kód ich len nespracoval.

Tento režim má rovnaký prísľub ako vo verzii 0.9: správy je možné spracovať, ale ak zlyhá, posun sa nemusí potvrdiť, čo môže spôsobiť zdvojnásobenie doručenia. Čím viac správ získate pri spustení anketa(), tým viac tento problém.

Ako je uvedené v časti “Čítanie správ z frontu” na strane 21, neexistuje nič také ako jednorazové doručenie správy v systéme správ, keď sa berú do úvahy režimy zlyhania.

V Kafke existujú dva spôsoby, ako vykonať (odovzdať) offset (offset): automaticky a manuálne. V oboch prípadoch môžu byť správy spracované viackrát, ak bola správa spracovaná, ale zlyhala pred odovzdaním. Môžete sa tiež rozhodnúť, že správu vôbec nespracujete, ak k odovzdaniu došlo na pozadí a váš kód bol dokončený skôr, ako mohol byť spracovaný (možno v Kafka 0.9 a staršom).

Proces manuálneho potvrdenia posunu v spotrebiteľskom rozhraní API Kafka môžete ovládať nastavením parametra povoliť.auto.potvrdenie na hodnotu false a explicitne volať jednu z nasledujúcich metód:

void commitSync();
void commitAsync();

Ak chcete správu spracovať „aspoň raz“, musíte vykonať posun manuálne pomocou commitSync()vykonaním tohto príkazu ihneď po spracovaní správ.

Tieto metódy neumožňujú potvrdzovať správy pred ich spracovaním, ale nerobia nič na to, aby eliminovali potenciálne oneskorenia pri spracovaní, pričom pôsobia ako transakčné. V Kafke nie sú žiadne transakcie. Klient nemá možnosť urobiť nasledovné:

  • Automaticky vrátiť falošnú správu späť. Samotní spotrebitelia musia zvládnuť výnimky vyplývajúce z problematického zaťaženia a výpadkov backendu, pretože sa nemôžu spoliehať na to, že sprostredkovateľ správy doručí znova.
  • Posielajte správy na viacero tém v jednej atómovej operácii. Ako čoskoro uvidíme, kontrola nad rôznymi témami a oddielmi sa môže nachádzať na rôznych počítačoch v klastri Kafka, ktoré pri odosielaní nekoordinujú transakcie. V čase písania tohto článku sa vykonala určitá práca, aby to bolo možné pomocou KIP-98.
  • Spojte čítanie jednej správy z jednej témy s odoslaním ďalšej správy na inú tému. Architektúra Kafky opäť závisí od mnohých nezávislých strojov bežiacich ako jedna zbernica a nesnažíme sa to zakryť. Napríklad neexistujú žiadne komponenty API, ktoré by vám umožnili prepojenie spotrebiteľ и producent v transakcii. V JMS to zabezpečuje objekt zasadnutiez ktorých sú vytvorené MessageProducers и MessageConsumers.

Ak sa nemôžeme spoľahnúť na transakcie, ako môžeme poskytnúť sémantiku bližšiu tej, ktorú poskytujú tradičné systémy zasielania správ?

Ak existuje možnosť, že posun spotrebiteľa sa môže zvýšiť pred spracovaním správy, ako napríklad počas zlyhania spotrebiteľa, potom spotrebiteľ nemá žiadny spôsob, ako zistiť, či jeho skupina spotrebiteľov nezmeškala správu, keď je mu priradený oddiel. Takže jednou stratégiou je previnúť offset na predchádzajúcu pozíciu. Spotrebiteľské API Kafka na to poskytuje nasledujúce metódy:

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

metóda hľadať () možno použiť s metódou
offsetsForTimes(Map timestampsToSearch) vrátiť sa do stavu v určitom konkrétnom bode v minulosti.

Použitie tohto prístupu implicitne znamená, že je veľmi pravdepodobné, že niektoré správy, ktoré boli predtým spracované, budú prečítané a spracované znova. Aby sme tomu zabránili, môžeme použiť idempotentné čítanie, ako je popísané v kapitole 4, na sledovanie predtým zobrazených správ a odstránenie duplikátov.

Alternatívne môže byť váš spotrebiteľský kód jednoduchý, pokiaľ je prijateľná strata alebo duplikácia správ. Keď vezmeme do úvahy prípady použitia, na ktoré sa Kafka bežne používa, ako je spracovanie udalostí denníka, metrík, sledovanie kliknutí atď., chápeme, že strata jednotlivých správ pravdepodobne nebude mať významný vplyv na okolité aplikácie. V takýchto prípadoch sú predvolené hodnoty úplne prijateľné. Na druhej strane, ak vaša aplikácia potrebuje posielať platby, musíte sa starostlivo starať o každú jednotlivú správu. Všetko závisí od kontextu.

Osobné pozorovania ukazujú, že so zvyšujúcou sa intenzitou správ klesá hodnota každej jednotlivej správy. Veľké správy majú tendenciu byť hodnotné, keď sú zobrazené v súhrnnej forme.

Vysoká dostupnosť

Kafkov prístup k vysokej dostupnosti je veľmi odlišný od prístupu ActiveMQ. Kafka je navrhnutá na základe škálovateľných klastrov, kde všetky inštancie makléra prijímajú a distribuujú správy v rovnakom čase.

Klaster Kafka pozostáva z viacerých inštancií makléra bežiacich na rôznych serveroch. Kafka bol navrhnutý tak, aby fungoval na bežnom samostatnom hardvéri, kde má každý uzol svoje vlastné vyhradené úložisko. Použitie sieťového úložiska (SAN) sa neodporúča, pretože o čas môže súťažiť viacero výpočtových uzlov.Ыe intervaly ukladania a vytvárajú konflikty.

Kafka je vždy zapnutý systém. Mnoho veľkých používateľov Kafka nikdy nevypne svoje klastre a softvér sa vždy aktualizuje sekvenčným reštartom. Dosahuje sa to zaručením kompatibility s predchádzajúcou verziou pre správy a interakcie medzi maklérmi.

Sprostredkovatelia pripojení ku klastru serverov Ošetrovateľ v zoo, ktorý funguje ako register konfiguračných údajov a používa sa na koordináciu rolí každého makléra. Samotný ZooKeeper je distribuovaný systém, ktorý poskytuje vysokú dostupnosť prostredníctvom replikácie informácií založením kvórum.

V základnom prípade sa téma vytvorí v klastri Kafka s nasledujúcimi vlastnosťami:

  • Počet oddielov. Ako bolo uvedené vyššie, presná hodnota, ktorá sa tu používa, závisí od požadovanej úrovne paralelného čítania.
  • Replikačný faktor (faktor) určuje, koľko inštancií sprostredkovateľa v klastri by malo obsahovať protokoly pre tento oddiel.

Pomocou ZooKeepers na koordináciu sa Kafka pokúša spravodlivo rozdeliť nové oddiely medzi maklérov v klastri. Robí to jedna inštancia, ktorá funguje ako Controller.

Za behu pre každý tematický oddiel kontrolór prideľovať role maklérovi vodca (vedúci, majster, uvádzač) a nasledovníkov (nasledovníci, otroci, podriadení). Sprostredkovateľ, ktorý pôsobí ako vedúci tohto oddielu, je zodpovedný za prijímanie všetkých správ, ktoré mu posielajú výrobcovia, a za distribúciu správ spotrebiteľom. Keď sa správy odošlú do tematického oddielu, replikujú sa na všetky uzly sprostredkovateľa, ktoré fungujú ako nasledovníci pre tento oddiel. Zavolá sa každý uzol obsahujúci protokoly pre oddiel replika. Maklér môže pôsobiť ako vedúci pre niektoré oddiely a ako nasledovník pre iné.

Volá sa nasledovník obsahujúci všetky správy, ktoré má vodca synchronizovaná replika (replika, ktorá je v synchronizovanom stave, synchronizovaná replika). Ak dôjde k výpadku sprostredkovateľa, ktorý pôsobí ako vedúci oddielu, úlohu vedúceho môže prevziať každý maklér, ktorý je aktuálny alebo synchronizovaný pre daný oddiel. Je to neuveriteľne udržateľný dizajn.

Súčasťou konfigurácie výrobcu je parameter acks, ktorý určuje, koľko replík musí potvrdiť (potvrdiť) prijatie správy predtým, ako vlákno aplikácie bude pokračovať v odosielaní: 0, 1 alebo všetky. Ak je nastavené na všetko, potom, keď je prijatá správa, vedúci pošle potvrdenie späť producentovi, len čo dostane potvrdenia (potvrdenia) záznamu z niekoľkých podnetov (vrátane seba) definovaných nastavením témy min.insync.repliky (predvolená hodnota 1). Ak správu nie je možné úspešne replikovať, potom výrobca vyvolá výnimku aplikácie (NotEnoughReplicas alebo NotEnoughReplicasAfterAppend).

Typická konfigurácia vytvorí tému s replikačným faktorom 3 (1 vedúci, 2 nasledovníci na oddiel) a parametrom min.insync.repliky je nastavená na 2. V tomto prípade klaster umožní jednému z maklérov spravujúcich tematický oddiel vypnúť bez ovplyvnenia klientskych aplikácií.

To nás privádza späť k už známemu kompromisu medzi výkonom a spoľahlivosťou. K replikácii dochádza na úkor dodatočnej doby čakania na potvrdenia (potvrdenia) od sledovateľov. Aj keď replikácia do najmenej troch uzlov má rovnaký výkon ako dva uzly, pretože beží paralelne (ignoruje sa nárast využitia šírky pásma siete).

Použitím tejto schémy replikácie sa Kafka šikovne vyhýba potrebe fyzického zapisovania každej správy na disk s operáciou sync(). Každá správa odoslaná výrobcom sa zapíše do protokolu oddielu, ale ako je uvedené v kapitole 2, zápis do súboru sa spočiatku vykonáva vo vyrovnávacej pamäti operačného systému. Ak je táto správa replikovaná na inú Kafkovu inštanciu a je v jej pamäti, strata lídra neznamená, že sa stratila samotná správa – môže ju prevziať synchronizovaná replika.
Odmietnutie vykonať operáciu sync() znamená, že Kafka môže prijímať správy tak rýchlo, ako ich dokáže zapisovať do pamäte. Naopak, čím dlhšie sa môžete vyhnúť vyplachovaniu pamäte na disk, tým lepšie. Z tohto dôvodu nie je nezvyčajné, že maklérom Kafka je pridelených 64 GB alebo viac pamäte. Toto využitie pamäte znamená, že jedna inštancia Kafka môže ľahko bežať tisíckrát rýchlejšími rýchlosťami ako tradičný sprostredkovateľ správ.

Kafka môže byť tiež nakonfigurovaný na použitie operácie sync() posielať správy balíkom. Keďže všetko v Kafke je orientované na balíky, v mnohých prípadoch použitia to funguje celkom dobre a je to užitočný nástroj pre používateľov, ktorí vyžadujú veľmi silné záruky. Veľká časť čistého výkonu Kafky pochádza zo správ, ktoré sa odosielajú sprostredkovateľovi ako pakety a tieto správy sa čítajú z sprostredkovateľa v sekvenčných blokoch pomocou nulová kópia operácie (operácie, počas ktorých sa nevykonáva úloha kopírovania údajov z jednej oblasti pamäte do druhej). Posledné z nich je veľkým ziskom z výkonu a zdrojov a je možné len pomocou základnej štruktúry údajov protokolu, ktorá definuje schému oddielov.

Oveľa lepší výkon je možný v klastri Kafka ako s jedným maklérom Kafka, pretože tematické oddiely sa môžu škálovať na mnohých samostatných počítačoch.

Výsledky

V tejto kapitole sme sa pozreli na to, ako architektúra Kafka pretvára vzťah medzi klientmi a maklérmi tak, aby poskytovala neuveriteľne robustný kanál na odosielanie správ s mnohonásobne vyššou priepustnosťou, než má bežný sprostredkovateľ správ. Diskutovali sme o funkcionalite, ktorú používa na dosiahnutie tohto cieľa, a stručne sme sa pozreli na architektúru aplikácií, ktoré túto funkcionalitu poskytujú. V ďalšej kapitole sa pozrieme na bežné problémy, ktoré musia aplikácie založené na správach riešiť, a rozoberieme stratégie, ako sa s nimi vysporiadať. Kapitolu zakončíme tým, že načrtneme, ako hovoriť o technológiách odosielania správ vo všeobecnosti, aby ste mohli zhodnotiť ich vhodnosť pre vaše prípady použitia.

Predchádzajúca preložená časť: Pochopenie sprostredkovateľov správ. Naučte sa mechaniku posielania správ pomocou ActiveMQ a Kafka. Kapitola 1

Preklad hotový: tele.gg/middle_java

Ak sa chcete pokračovať ...

Do prieskumu sa môžu zapojiť iba registrovaní užívatelia. Prihlásiť saProsím.

Používa sa vo vašej organizácii Kafka?

  • Да

  • Nie

  • Predtým používané, teraz nie

  • Plánujeme použiť

Hlasovalo 38 užívateľov. 8 užívateľov sa zdržalo hlasovania.

Zdroj: hab.com

Pridať komentár