Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka

Mažos knygelės vertimo tęsinys:
Žinučių brokerių supratimas
autorius: Jakub Korab, leidėjas: O'Reilly Media, Inc., išleidimo data: 2017 m. birželio mėn., ISBN: 9781492049296.

Ankstesnė išversta dalis: Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 1 skyrius Įvadas

3 SKYRIUS

Kafka

„Kafka“ buvo sukurta „LinkedIn“, siekiant apeiti kai kuriuos tradicinių pranešimų tarpininkų apribojimus ir išvengti kelių pranešimų tarpininkų, skirtų skirtingoms tiesioginėms sąveikoms, kurios aprašytos šios knygos skyriuje „Mastelio padidinimas ir sumažinimas“, 28 puslapyje. Naudojimo atvejai „LinkedIn“ daugiausia rėmėsi vienpusiu labai didelio duomenų kiekio, pvz., puslapių paspaudimų ir prieigos žurnalų, gavimu, tuo pačiu leisdama tuos duomenis naudoti keliose sistemose nepakenkiant gamintojų ar kitų vartotojų produktyvumui. Tiesą sakant, priežastis, dėl kurios Kafka egzistuoja, yra gauti tokią pranešimų siuntimo architektūrą, kurią aprašo Universal Data Pipeline.

Atsižvelgiant į šį galutinį tikslą, natūraliai iškilo kiti reikalavimai. Kafka turėtų:

  • Būkite itin greiti
  • Suteikite daugiau pralaidumo dirbdami su pranešimais
  • Palaikykite leidėjo-abonento ir „point-to-point“ modelius
  • Nesulėtinkite pridedant vartotojų. Pavyzdžiui, tiek eilės, tiek temos našumas ActiveMQ prastėja, nes didėja vartotojų skaičius paskirties vietoje.
  • būti horizontaliai keičiamo mastelio; jei vienas tarpininkas, kuris nuolat gauna pranešimus, gali tai padaryti tik maksimaliu disko greičiu, prasminga naudoti daugiau nei vieną tarpininko egzempliorių, kad padidintumėte našumą
  • Apriboti prieigą prie pranešimų saugojimo ir pakartotinio gavimo

Kad visa tai pasiektų, Kafka priėmė architektūrą, kuri iš naujo apibrėžė klientų ir žinučių siuntimo brokerių vaidmenis ir atsakomybę. JMS modelis yra labai orientuotas į tarpininką, kur brokeris yra atsakingas už pranešimų platinimą, o klientams belieka rūpintis žinučių siuntimu ir gavimu. Kita vertus, „Kafka“ yra orientuota į klientą – klientas perima daugelį tradicinio brokerio bruožų, pavyzdžiui, sąžiningą aktualių pranešimų paskirstymą vartotojams, mainais į itin greitą ir keičiamo dydžio brokerį. Žmonėms, kurie dirbo su tradicinėmis pranešimų siuntimo sistemomis, darbas su Kafka reikalauja iš esmės pakeisti mąstymą.
Ši inžinerinė kryptis leido sukurti pranešimų infrastruktūrą, galinčią padidinti pralaidumą daugeliu dydžių, palyginti su įprastu brokeriu. Kaip matysime, šis požiūris yra susijęs su kompromisais, o tai reiškia, kad „Kafka“ netinka tam tikram darbo krūviui ir įdiegtai programinei įrangai.

Vieningas paskirties modelis

Siekdama įvykdyti aukščiau aprašytus reikalavimus, Kafka sujungė publikavimo-prenumeratos ir tiesioginio ryšio pranešimų siuntimą pagal vieną paskirties vietą. tema. Tai glumina žmones, dirbusius su pranešimų siuntimo sistemomis, kur žodis „tema“ reiškia transliavimo mechanizmą, iš kurio (iš temos) skaitymas yra netvarus. Kafkos temos turėtų būti laikomos hibridiniu paskirties tipu, kaip apibrėžta šios knygos įžangoje.

Likusioje šio skyriaus dalyje, jei aiškiai nenurodysime kitaip, terminas „tema“ reiškia Kafkos temą.

Norėdami visiškai suprasti, kaip temos elgiasi ir kokias garantijas jos suteikia, pirmiausia turime pažvelgti į tai, kaip jos įgyvendinamos Kafkoje.
Kiekviena Kafkos tema turi savo žurnalą.
Gamintojai, siunčiantys pranešimus Kafkai, rašo į šį žurnalą, o vartotojai skaito iš žurnalo naudodami nuorodas, kurios nuolat juda į priekį. Periodiškai Kafka ištrina seniausias žurnalo dalis, nesvarbu, ar tose dalyse esantys pranešimai buvo perskaityti, ar ne. Pagrindinė Kafkos dizaino dalis yra ta, kad brokeriui nerūpi, ar pranešimai skaitomi, ar ne – tai kliento atsakomybė.

Sąvokų „logas“ ir „rodiklis“ nėra Kafkos dokumentacija. Šie gerai žinomi terminai čia naudojami siekiant padėti suprasti.

Šis modelis visiškai skiriasi nuo ActiveMQ, kur visų eilių pranešimai saugomi tame pačiame žurnale, o tarpininkas pranešimus pažymi kaip ištrintus po to, kai jie buvo perskaityti.
Dabar pasigilinkime šiek tiek giliau ir pažvelkime į temų žurnalą išsamiau.
Kafka žurnalas susideda iš kelių pertvarų (Pav 3-1). Kafka garantuoja griežtą tvarką kiekvienoje pertvaroje. Tai reiškia, kad tam tikra tvarka į skaidinį parašyti pranešimai bus skaitomi ta pačia tvarka. Kiekvienas skaidinys įgyvendinamas kaip slenkantis žurnalo failas, kuriame yra poaibis (pogrupis) visų pranešimų, kuriuos tema siunčia jos kūrėjai. Sukurtoje temoje pagal numatytuosius nustatymus yra vienas skaidinys. Pertvarų idėja yra pagrindinė Kafkos idėja horizontaliam mastelio keitimui.

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-1 pav. Kafka pertvaros

Kai gamintojas siunčia pranešimą Kafkos tema, jis nusprendžia, į kurį skyrių siųsti pranešimą. Išsamiau tai panagrinėsime vėliau.

Pranešimų skaitymas

Klientas, norintis perskaityti pranešimus, valdo pavadintą žymeklį vartotojų grupė, kuris nurodo kompensuoti žinutes skaidinyje. Poslinkis yra prieauginė padėtis, kuri prasideda nuo 0 skaidinio pradžioje. Ši vartotojų grupė, nurodyta API per vartotojo nustatytą group_id, atitinka vienas logiškas vartotojas arba sistema.

Dauguma pranešimų sistemų nuskaito duomenis iš paskirties vietos, naudodamos kelis egzempliorius ir gijas, kad lygiagrečiai apdorotų pranešimus. Taigi paprastai bus daug vartotojų, kurie dalijasi ta pačia vartotojų grupe.

Skaitymo problemą galima pavaizduoti taip:

  • Tema turi keletą skaidinių
  • Kelios vartotojų grupės gali naudoti temą vienu metu
  • Vartotojų grupė gali turėti kelis atskirus atvejus

Tai nebanali „daugelis prieš daugelį“ problema. Norėdami suprasti, kaip Kafka tvarko santykius tarp vartotojų grupių, vartotojų egzempliorių ir skaidinių, pažvelkime į vis sudėtingesnius skaitymo scenarijus.

Vartotojai ir vartotojų grupės

Pradėkime nuo temos su vienu skirsniu (Pav 3-2).

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-2 pav. Vartotojas skaito iš skaidinio

Kai vartotojo egzempliorius prisijungia prie šios temos su savo grupės_id, jam priskiriamas skaitymo skaidinys ir poslinkis tame skaidinyje. Šio poslinkio padėtis kliente sukonfigūruojama kaip rodyklė į naujausią poziciją (naujausias pranešimas) arba anksčiausią poziciją (seniausias pranešimas). Vartotojas prašo (apklausia) pranešimų iš temos, todėl jie nuosekliai skaitomi iš žurnalo.
Poslinkio pozicija reguliariai grąžinama Kafkai ir saugoma kaip pranešimai vidinėje temoje _consumer_offsets. Skaityti pranešimai vis tiek neištrinami, skirtingai nei įprastas brokeris, o klientas gali atsukti poslinkį, kad iš naujo apdorotų jau peržiūrėtus pranešimus.

Kai antrasis loginis vartotojas prisijungia naudodamas kitą group_id, jis valdo antrąjį žymeklį, kuris nepriklauso nuo pirmojo (Pav 3-3). Taigi, Kafka tema veikia kaip eilė, kurioje yra vienas vartotojas, ir kaip įprasta publikavimo-prenumeratos (pub-sub) tema, kurią prenumeruoja keli vartotojai, o tai papildoma nauda, ​​kad visi pranešimai yra saugomi ir gali būti tvarkomi kelis kartus.

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-3 pav. Du vartotojai skirtingose ​​vartotojų grupėse skaito iš to paties skirsnio

Vartotojai vartotojų grupėje

Kai vienas vartotojo egzempliorius nuskaito duomenis iš skaidinio, jis visiškai valdo žymeklį ir apdoroja pranešimus, kaip aprašyta ankstesniame skyriuje.
Jei keli vartotojų atvejai buvo sujungti su tuo pačiu group_id prie temos su vienu skaidiniu, tada egzempliorius, kuris prisijungė paskutinis, turės valdyti žymeklį ir nuo to momento jis gaus visus pranešimus (Pav 3-4).

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-4 pav. Du vartotojai toje pačioje vartotojų grupėje skaito iš to paties skaidinio

Šis apdorojimo būdas, kai vartotojų egzempliorių skaičius viršija skaidinių skaičių, gali būti laikomas savotišku išskirtiniu vartotoju. Tai gali būti naudinga, jei jums reikia „aktyvus-pasyvus“ (arba „karštas-šiltas“) vartotojų egzempliorių grupių, nors kelių vartotojų paleidimas lygiagrečiai („aktyvus-aktyvus“ arba „karštas“) yra daug labiau būdingas nei budėjimo režimu.

Šis aukščiau aprašytas pranešimų platinimo elgesys gali nustebinti, palyginti su įprastos JMS eilės elgesiu. Šiame modelyje į eilę siunčiami pranešimai bus tolygiai paskirstyti tarp dviejų vartotojų.

Dažniausiai, kai sukuriame kelis vartotojų atvejus, tai darome norėdami lygiagrečiai apdoroti pranešimus arba padidinti skaitymo greitį, arba padidinti skaitymo proceso stabilumą. Kadangi duomenis iš skaidinio vienu metu gali nuskaityti tik vienas vartotojo egzempliorius, kaip tai pasiekiama Kafkoje?

Vienas iš būdų tai padaryti yra naudoti vieną vartotojo egzempliorių, kad perskaitytų visus pranešimus ir perduotų juos gijų telkiniui. Nors šis metodas padidina apdorojimo pralaidumą, jis padidina vartotojo logikos sudėtingumą ir nepadidina skaitymo sistemos patikimumo. Jei vienas vartotojo egzempliorius sugenda dėl elektros energijos tiekimo sutrikimo ar panašaus įvykio, atimtis sustoja.

Kanoninis būdas išspręsti šią problemą Kafkoje yra naudoti bОdaugiau pertvarų.

Skirstymas

Pertvaros yra pagrindinis mechanizmas, leidžiantis lygiagrečiai skaityti ir keisti temą, neviršijant vieno tarpininko egzemplioriaus pralaidumo. Norėdami tai geriau suprasti, panagrinėkime situaciją, kai yra tema su dviem skaidiniais ir vienas vartotojas užsiprenumeruoja šią temą (Pav 3-5).

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-5 pav. Vienas vartotojas skaito iš kelių skaidinių

Pagal šį scenarijų vartotojui suteikiama valdyti rodykles, atitinkančias jo group_id abiejuose skaidiniuose, ir jis pradeda skaityti pranešimus iš abiejų skaidinių.
Kai prie šios temos pridedamas papildomas tos pačios grupės_id vartotojas, Kafka perskirsto vieną iš skaidinių iš pirmojo į antrąjį vartotoją. Po to kiekvienas vartotojo egzempliorius skaitys iš vienos temos dalies (Pav 3-6).

Norint užtikrinti, kad pranešimai būtų apdorojami lygiagrečiai 20 gijų, reikia bent 20 skaidinių. Jei skirsnių bus mažiau, liks vartotojai, kurie neturi prie ko dirbti, kaip aprašyta anksčiau diskusijoje apie išskirtinius vartotojus.

Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 3 skyrius. Kafka
3-6 pav. Du tos pačios vartotojų grupės vartotojai skaito iš skirtingų skaidinių

Ši schema labai sumažina Kafka brokerio sudėtingumą, palyginti su pranešimų paskirstymu, reikalingu JMS eilei palaikyti. Čia jums nereikia jaudintis dėl šių dalykų:

  • Kuris vartotojas turėtų gauti kitą pranešimą, atsižvelgiant į apvalų paskirstymą, esamą išankstinio gavimo buferių talpą arba ankstesnius pranešimus (kaip ir JMS pranešimų grupėms).
  • Kokie pranešimai kokiems vartotojams siunčiami ir ar gedimo atveju jie turėtų būti pateikiami pakartotinai.

Viskas, ką „Kafka“ brokeris turi padaryti, tai nuosekliai perduoti pranešimus vartotojui, kai pastarasis to prašo.

Tačiau reikalavimai lygiagrečiai korektūros skaitymui ir nepavykusių pranešimų siuntimui iš naujo niekur nedingsta – atsakomybė už juos tiesiog pereina nuo brokerio klientui. Tai reiškia, kad į juos turi būti atsižvelgta jūsų kode.

Siunčiamos žinutės

To pranešimo gamintojas turi nuspręsti, į kurį skyrių siųsti pranešimą. Norėdami suprasti mechanizmą, kuriuo tai daroma, pirmiausia turime apsvarstyti, ką iš tikrųjų siunčiame.

JMS mes naudojame pranešimo struktūrą su metaduomenimis (antraštėmis ir ypatybėmis) ir turiniu, kuriame yra naudingoji apkrova (naudingoji apkrova), o Kafkoje pranešimas yra pora "rakto vertė". Pranešimo naudingoji apkrova siunčiama kaip vertė. Kita vertus, raktas daugiausia naudojamas skaidymui ir turi būti konkretus verslo logikos raktasNorėdami įdėti susijusius pranešimus į tą patį skaidinį.

2 skyriuje aptarėme internetinių lažybų scenarijų, kai susijusius įvykius turi apdoroti vienas vartotojas:

  1. Vartotojo paskyra sukonfigūruota.
  2. Pinigai įskaitomi į sąskaitą.
  3. Atliekamas statymas, kurio metu iš sąskaitos išimami pinigai.

Jei kiekvienas įvykis yra žinutė, paskelbta temoje, natūralus raktas būtų paskyros ID.
Kai pranešimas siunčiamas naudojant Kafka Producer API, jis perduodamas skaidinio funkcijai, kuri, atsižvelgiant į pranešimą ir esamą Kafka klasterio būseną, grąžina skaidinio, į kurį turi būti išsiųstas pranešimas, ID. Ši funkcija įdiegta „Java“ per „Partitioner“ sąsają.

Ši sąsaja atrodo taip:

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

Skirstytuvo diegimas naudoja numatytąjį bendrosios paskirties maišos algoritmą per raktą, kad nustatytų skaidinį, arba apvalų patikrinimą, jei nenurodytas joks raktas. Ši numatytoji reikšmė daugeliu atvejų veikia gerai. Tačiau ateityje norėsite parašyti savo.

Savo skaidymo strategijos rašymas

Pažvelkime į pavyzdį, kai norite siųsti metaduomenis kartu su pranešimo apkrova. Mūsų pavyzdyje naudingas krovinys yra nurodymas įnešti įmoką į žaidimo sąskaitą. Instrukcija yra kažkas, dėl ko mes norėtume būti garantuoti, kad jie nebus modifikuoti perduodant, ir norime būti tikri, kad tik patikima aukštesnė sistema gali inicijuoti tą nurodymą. Tokiu atveju siunčiančios ir priimančios sistemos susitaria dėl parašo naudojimo pranešimo autentifikavimui.
Įprastoje JMS mes tiesiog apibrėžiame "pranešimo parašo" ypatybę ir pridedame ją prie pranešimo. Tačiau Kafka nepateikia mums metaduomenų perdavimo mechanizmo, tik raktą ir reikšmę.

Kadangi reikšmė yra banko pavedimo naudingoji apkrova, kurios vientisumą norime išsaugoti, neturime kito pasirinkimo, kaip tik apibrėžti duomenų struktūrą, kurią naudosime rakte. Darant prielaidą, kad norint skaidyti mums reikia paskyros ID, nes visi su paskyra susiję pranešimai turi būti apdoroti eilės tvarka, mes sukursime tokią JSON struktūrą:

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

Kadangi parašo reikšmė skirsis priklausomai nuo naudingojo krovinio, numatytoji skirstytuvo sąsajos maišos strategija patikimai sugrupuos susijusius pranešimus. Todėl turėsime parašyti savo strategiją, kuri išnagrinės šį raktą ir padalins accountId reikšmę.

Kafka apima kontrolines sumas, skirtas aptikti sugadintus pranešimus parduotuvėje, ir turi visą saugos funkcijų rinkinį. Nepaisant to, kartais atsiranda specifinių pramonės šakų reikalavimų, tokių kaip aukščiau pateiktas.

Vartotojo skaidymo strategija turi užtikrinti, kad visi susiję pranešimai patektų į tą patį skaidinį. Nors tai atrodo paprasta, reikalavimą gali apsunkinti susijusių įrašų užsakymo svarba ir tai, kaip fiksuotas temoje esančių skaidinių skaičius.

Skyrių skaičius temoje laikui bėgant gali keistis, nes juos galima pridėti, jei srautas viršija pradinius lūkesčius. Taigi pranešimų raktai gali būti susieti su skaidiniu, į kurį jie buvo išsiųsti iš pradžių, o tai reiškia, kad būsenos dalis turi būti dalijama tarp gamintojų egzempliorių.

Kitas veiksnys, į kurį reikia atsižvelgti, yra tolygus pranešimų paskirstymas skaidiniuose. Paprastai raktai nėra tolygiai paskirstomi pranešimuose, o maišos funkcijos negarantuoja teisingo pranešimų paskirstymo nedideliam raktų rinkiniui.
Svarbu pažymėti, kad nepaisant to, kad pasirinksite skaidyti pranešimus, patį skyriklį gali tekti naudoti pakartotinai.

Apsvarstykite reikalavimą pakartoti duomenis tarp Kafka grupių skirtingose ​​geografinėse vietose. Šiuo tikslu „Kafka“ turi komandinės eilutės įrankį „MirrorMaker“, kuris naudojamas žinutėms iš vienos grupės skaityti ir perkelti į kitą.

„MirrorMaker“ turi suprasti replikuotos temos raktus, kad išlaikytų santykinę tvarką tarp pranešimų, kai replikuojasi tarp grupių, nes tos temos skaidinių skaičius dviejuose klasteriuose gali būti nevienodas.

Individualizuotos skaidymo strategijos yra gana retos, nes numatytasis maišymas arba apvalumas veikia gerai daugelyje scenarijų. Tačiau jei jums reikalingos tvirtos užsakymo garantijos arba reikia išgauti metaduomenis iš naudingų krovinių, tuomet turėtumėte atidžiau pažvelgti į skaidymą.

„Kafka“ mastelio keitimo ir našumo pranašumai atsiranda dėl kai kurių tradicinio brokerio pareigų perkėlimo klientui. Tokiu atveju priimamas sprendimas platinti galimai susijusias žinutes tarp kelių lygiagrečiai dirbančių vartotojų.

JMS brokeriai taip pat turi atsižvelgti į tokius reikalavimus. Įdomu tai, kad susijusių pranešimų siuntimo tam pačiam vartotojui mechanizmas, įdiegtas per JMS pranešimų grupes (priklijuotos apkrovos balansavimo (SLB) strategijos variantas), taip pat reikalauja, kad siuntėjas pažymėtų pranešimus kaip susijusius. JMS atveju brokeris yra atsakingas už šios susijusių pranešimų grupės siuntimą vienam vartotojui iš daugelio ir grupės nuosavybės perdavimą, jei vartotojas atsisako.

Gamintojų susitarimai

Skaičiavimas nėra vienintelis dalykas, į kurį reikia atsižvelgti siunčiant pranešimus. Pažvelkime į „Java“ API „Producer“ klasės siuntimo () metodus:

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

Iš karto reikia pažymėti, kad abu metodai grąžina Future, o tai rodo, kad siuntimo operacija neatliekama iš karto. Rezultatas yra tai, kad pranešimas (ProducerRecord) įrašomas į kiekvieno aktyvaus skaidinio siuntimo buferį ir siunčiamas tarpininkui kaip foninė gija Kafka kliento bibliotekoje. Nors tai daro viską neįtikėtinai greitai, tai reiškia, kad nepatyrusi programa gali prarasti pranešimus, jei jos procesas bus sustabdytas.

Kaip visada, yra būdas padaryti siuntimo operaciją patikimesnę našumo kaina. Šio buferio dydis gali būti nustatytas į 0, o siuntimo programos gija bus priversta laukti, kol bus baigtas pranešimo perdavimas tarpininkui, kaip nurodyta toliau:

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

Daugiau apie pranešimų skaitymą

Laiškų skaitymas turi papildomų sudėtingų dalykų, dėl kurių reikia spėlioti. Skirtingai nuo JMS API, kuri, reaguodama į pranešimą, gali paleisti pranešimų klausytoją Vartotojas Kafka tik apklausas. Pažvelkime atidžiau į metodą apklausa ()naudojami šiam tikslui:

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

Metodo grąžinama vertė yra konteinerio struktūra, kurioje yra keli objektai vartotojų įrašas iš potencialiai kelių pertvarų. vartotojų įrašas pats yra rakto ir reikšmių poros su susijusiais metaduomenimis, pvz., skaidiniu, iš kurio jie gaunami, laikymo objektas.

Kaip aptarta 2 skyriuje, turime nepamiršti, kas nutinka žinutėms po to, kai jie buvo sėkmingai arba nesėkmingai apdoroti, pavyzdžiui, jei klientas negali apdoroti pranešimo arba jis nutrūksta. JMS tai buvo tvarkoma naudojant patvirtinimo režimą. Tarpininkas arba ištrins sėkmingai apdorotą pranešimą, arba iš naujo pateiks neapdorotą arba netikrą pranešimą (darant prielaidą, kad buvo panaudotos operacijos).
Kafka veikia labai skirtingai. Po korektūros pranešimai brokeryje neištrinami, o už tai, kas atsitiks nesėkmės atveju, atsako pats korektūros kodas.

Kaip jau minėjome, vartotojų grupė yra susieta su užskaita žurnale. Su šiuo poslinkiu susieta žurnalo padėtis atitinka kitą pranešimą, į kurį bus atsakyta apklausa (). Laikas, kada šis poslinkis padidėja, yra lemiamas skaitymui.

Grįžtant prie anksčiau aptarto skaitymo modelio, pranešimų apdorojimas susideda iš trijų etapų:

  1. Gaukite pranešimą skaitymui.
  2. Apdorokite pranešimą.
  3. Patvirtinkite pranešimą.

„Kafka“ vartotojas turi konfigūravimo parinktį enable.auto.commit. Tai dažnai naudojamas numatytasis nustatymas, kaip ir nustatymuose, kuriuose yra žodis „automatinis“.

Prieš Kafka 0.10, klientas, naudodamas šią parinktį, siųsdavo paskutinio skaityto pranešimo poslinkį kito skambučio metu apklausa () po apdorojimo. Tai reiškė, kad bet kokie pranešimai, kurie jau buvo gauti, gali būti apdoroti iš naujo, jei klientas jau juos apdorojo, bet buvo netikėtai sunaikintas prieš skambinant. apklausa (). Kadangi tarpininkas neišsaugo jokios informacijos apie tai, kiek kartų pranešimas buvo perskaitytas, kitas vartotojas, nuskaitęs tą pranešimą, nesužinos, kad nutiko nieko blogo. Toks elgesys buvo pseudo-sandoris. Poslinkis buvo atliktas tik tuo atveju, jei pranešimas buvo sėkmingai apdorotas, bet jei klientas nutraukė veiklą, brokeris vėl išsiųs tą patį pranešimą kitam klientui. Toks elgesys atitiko pranešimo pristatymo garantiją.nors karta"

Kafka 0.10 kliento kodas buvo pakeistas taip, kad kliento biblioteka periodiškai suaktyvintų įsipareigojimą, kaip sukonfigūruota auto.commit.interval.ms. Šis elgesys yra kažkur tarp JMS AUTO_ACKNOWLEDGE ir DUPS_OK_ACKNOWLEDGE režimų. Naudojant automatinį patvirtinimą, pranešimai gali būti perduodami neatsižvelgiant į tai, ar jie iš tikrųjų buvo apdoroti – taip gali nutikti lėto vartotojo atveju. Jei vartotojas nutrauktų veiklą, pranešimus gautų kitas vartotojas, pradedant nuo įsipareigojimo, todėl pranešimas gali būti praleistas. Šiuo atveju Kafka pranešimų neprarado, skaitymo kodas jų tiesiog neapdorojo.

Šis režimas turi tą patį pažadą kaip ir 0.9 versijoje: pranešimus galima apdoroti, bet jei nepavyksta, kompensacija gali būti neįgyvendinta, todėl pristatymas gali būti padvigubintas. Kuo daugiau pranešimų gausite vykdydami apklausa (), tuo daugiau šios problemos.

Kaip aptarta „Pranešimų skaitymas iš eilės“, 21 puslapyje, nėra tokio dalyko kaip vienkartinis pranešimo pristatymas pranešimų sistemoje, kai atsižvelgiama į gedimo būdus.

Kafkoje yra du būdai, kaip atlikti (įvesti) poslinkį (poslinkį): automatiškai ir rankiniu būdu. Abiem atvejais pranešimus galima apdoroti kelis kartus, jei pranešimas buvo apdorotas, bet nepavyko prieš patvirtinant. Taip pat galite pasirinkti visai neapdoroti pranešimo, jei įsipareigojimas įvyko fone ir jūsų kodas buvo užpildytas anksčiau nei buvo galima jį apdoroti (galbūt Kafka 0.9 ir senesnėse versijose).

Galite valdyti rankinio poslinkio įpareigojimo procesą Kafka vartotojo API nustatydami parametrą enable.auto.commit klaidingai ir aiškiai iškviečia vieną iš šių metodų:

void commitSync();
void commitAsync();

Jei norite apdoroti pranešimą „bent vieną kartą“, poslinkį turite atlikti rankiniu būdu naudodami commitSync()Vykdydami šią komandą iš karto po pranešimų apdorojimo.

Šie metodai neleidžia patvirtinti pranešimų prieš juos apdorojant, tačiau jie nepadeda pašalinti galimų apdorojimo delsų ir atrodo, kad tai yra operacija. Kafkoje nėra jokių sandorių. Klientas neturi galimybės atlikti šių veiksmų:

  • Automatiškai atšaukti suklastotą pranešimą. Vartotojai patys turi tvarkyti išimtis, atsirandančias dėl probleminių naudingų apkrovų ir užpakalinės sistemos gedimų, nes jie negali pasikliauti, kad tarpininkas pakartotinai pristatys pranešimus.
  • Siųskite pranešimus keliomis temomis vienu atominiu veiksmu. Kaip pamatysime netrukus, skirtingų temų ir skaidinių valdymas gali būti skirtinguose Kafka klasterio kompiuteriuose, kurie nekoordinuoja operacijų, kai siunčiami. Šio rašymo metu buvo atliktas tam tikras darbas, kad tai būtų įmanoma naudojant KIP-98.
  • Vieno pranešimo iš vienos temos skaitymą susiekite su kitos žinutės siuntimu kita tema. Vėlgi, Kafkos architektūra priklauso nuo daugybės nepriklausomų mašinų, veikiančių kaip viena magistralė, ir to nebandoma nuslėpti. Pavyzdžiui, nėra API komponentų, kurie leistų susieti vartotojas и Gamintojas sandoryje. JMS tai suteikia objektas Sesijaiš kurių kuriami MessageProducers и MessageConsumers.

Jei negalime pasikliauti transakcijomis, kaip galime pateikti semantiką, artimesnę tradicinėms pranešimų sistemoms?

Jei yra tikimybė, kad vartotojo užskaita gali padidėti prieš apdorojant pranešimą, pvz., vartotojui įvykus avarijai, vartotojas negali žinoti, ar jo vartotojų grupė praleido pranešimą, kai jam buvo priskirtas skyrius. Taigi viena strategija yra atsukti poslinkį į ankstesnę padėtį. „Kafka“ vartotojų API pateikia šiuos metodus:

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

metodas Ieškoti() gali būti naudojamas su metodu
offsetsFor Times (žemėlapis Paieškos laiko žymos) atsukti į būseną tam tikru konkrečiu praeities momentu.

Netiesiogiai naudojant šį metodą labai tikėtina, kad kai kurie anksčiau apdoroti pranešimai bus perskaityti ir apdoroti dar kartą. Norėdami to išvengti, galime naudoti idempotentinį skaitymą, kaip aprašyta 4 skyriuje, kad galėtume sekti anksčiau peržiūrėtus pranešimus ir pašalinti pasikartojančius pranešimus.

Arba jūsų vartotojo kodas gali būti paprastas, jei pranešimo praradimas arba kopijavimas yra priimtinas. Atsižvelgdami į naudojimo atvejus, kuriems dažniausiai naudojama Kafka, pvz., tvarkyti žurnalo įvykius, metriką, sekti paspaudimus ir kt., suprantame, kad atskirų pranešimų praradimas greičiausiai neturės reikšmingos įtakos aplinkinėms programoms. Tokiais atvejais numatytosios vertės yra visiškai priimtinos. Kita vertus, jei jūsų programai reikia siųsti mokėjimus, turite atidžiai pasirūpinti kiekvienu atskiru pranešimu. Viskas priklauso nuo konteksto.

Asmeniniai stebėjimai rodo, kad didėjant pranešimų intensyvumui, kiekvieno atskiro pranešimo vertė mažėja. Didelės žinutės paprastai būna vertingos, kai žiūrima apibendrinta forma.

Aukštas prieinamumas

Kafkos požiūris į aukštą prieinamumą labai skiriasi nuo ActiveMQ požiūrio. „Kafka“ yra sukurta aplink išplėstines grupes, kuriose visi tarpininkų egzemplioriai gauna ir platina pranešimus tuo pačiu metu.

„Kafka“ klasterį sudaro keli tarpininko egzemplioriai, veikiantys skirtinguose serveriuose. „Kafka“ buvo sukurta veikti naudojant įprastą atskirą aparatinę įrangą, kur kiekvienas mazgas turi savo saugyklą. Nerekomenduojama naudoti tinklo prijungtos saugyklos (SAN), nes keli skaičiavimo mazgai gali konkuruoti dėl laiko.Ыe saugojimo intervalus ir sukelti konfliktus.

Kafka yra visada sistema. Daugelis didelių Kafka vartotojų niekada neišjungia savo grupių, o programinė įranga visada atnaujinama nuosekliai paleidžiant iš naujo. Tai pasiekiama garantuojant pranešimų ir tarpininkų sąveikos suderinamumą su ankstesne versija.

Brokeriai prisijungę prie serverių klasterio Zoologijos sodo prižiūrėtojas, kuris veikia kaip konfigūracijos duomenų registras ir yra naudojamas koordinuoti kiekvieno brokerio vaidmenis. Pati „ZooKeeper“ yra paskirstyta sistema, kuri užtikrina aukštą prieinamumą, replikuojant informaciją kvorumas.

Baziniu atveju tema sukuriama Kafka klasteryje su šiomis savybėmis:

  • Pertvarų skaičius. Kaip aptarta anksčiau, tiksli čia naudojama reikšmė priklauso nuo norimo lygiagretaus skaitymo lygio.
  • Replikacijos koeficientas (faktorius) nustato, kiek tarpininkavimo atvejų klasteryje turi turėti šio skaidinio žurnalus.

Naudodamas „ZooKeepers“ koordinavimui, Kafka bando teisingai paskirstyti naujus skirsnius tarp klasterio brokerių. Tai atlieka vienas egzempliorius, kuris veikia kaip valdiklis.

Vykdymo metu kiekvienam temos skyriui Valdiklis paskirstyti vaidmenis brokeriui lyderis (vadovas, meistras, vedėjas) ir sekėjų (pasekėjai, vergai, pavaldiniai). Brokeris, eidamas šios srities lyderio pareigas, yra atsakingas už visų gamintojų jam siunčiamų žinučių priėmimą ir žinučių platinimą vartotojams. Kai pranešimai siunčiami į temos skaidinį, jie pakartojami visiems tarpininko mazgams, kurie veikia kaip to skaidinio sekėjai. Iškviečiamas kiekvienas mazgas, kuriame yra skaidinio žurnalai replika. Brokeris gali veikti kaip kai kurių skyrių vadovas, o kitų – kaip sekėjas.

Iškviečiamas sekėjas, kuriame yra visi lyderio turimi pranešimai sinchronizuota kopija (replika, kuri yra sinchronizuotos būsenos, sinchronizuota kopija). Jei brokeris, veikiantis kaip skaidinio vadovas, nustoja veikti, bet kuris atnaujintas arba sinchronizuotas tarpininkas gali perimti lyderio vaidmenį. Tai neįtikėtinai tvarus dizainas.

Gamintojo konfigūracijos dalis yra parametras acks, kuris nustato, kiek kopijų turi patvirtinti (patvirtinti) pranešimo gavimą, kad programos gija toliau siųstų: 0, 1 arba visi. Jei nustatyta visi, tada, kai bus gautas pranešimas, vadovas išsiųs patvirtinimą atgal gamintojui, kai tik jis gaus įrašo patvirtinimus (patvirtinimus) iš kelių užuominų (įskaitant save), apibrėžtų temos nustatymu. min.insync.replicas (numatytasis 1). Jei pranešimo nepavyksta sėkmingai kopijuoti, gamintojas išmes programos išimtį (NotEnoughReplicas arba NotEnoughReplicasAfterAppend).

Įprasta konfigūracija sukuria temą, kurios replikacijos koeficientas yra 3 (1 vadovas, 2 sekėjai viename skaidinyje) ir parametru min.insync.replicas yra nustatytas į 2. Šiuo atveju klasteris leis vienam iš tarpininkų, valdančių temos skaidinį, nedarant įtakos kliento programoms.

Tai sugrąžina mus prie jau pažįstamo kompromiso tarp našumo ir patikimumo. Replikacija vyksta dėl papildomo sekėjų patvirtinimų (patvirtinimų) laukimo laiko. Nors, kadangi jis veikia lygiagrečiai, replikacijos į mažiausiai tris mazgus našumas yra toks pat kaip dviejų (neatsižvelgiant į tinklo pralaidumo padidėjimą).

Naudodamas šią replikacijos schemą, Kafka sumaniai išvengia poreikio fiziškai įrašyti kiekvieną pranešimą į diską su operacija sync(). Kiekvienas gamintojo atsiųstas pranešimas bus įrašytas į skaidinio žurnalą, tačiau, kaip aptarta 2 skyriuje, iš pradžių įrašymas į failą atliekamas operacinės sistemos buferyje. Jei ši žinutė yra atkartota į kitą Kafkos egzempliorių ir yra jo atmintyje, lyderio praradimas nereiškia, kad buvo prarastas pats pranešimas – jį gali perimti sinchronizuota kopija.
Atsisakymas atlikti operaciją sync() reiškia, kad Kafka gali gauti pranešimus taip greitai, kaip gali įrašyti juos į atmintį. Ir atvirkščiai, kuo ilgiau išvengsite atminties plovimo į diską, tuo geriau. Dėl šios priežasties Kafka brokeriams neretai skiriama 64 GB ar daugiau atminties. Šis atminties naudojimas reiškia, kad vienas Kafka egzempliorius gali lengvai veikti daug tūkstančių kartų greičiau nei tradicinis pranešimų tarpininkas.

„Kafka“ taip pat gali būti sukonfigūruotas, kad būtų pritaikyta operacija sync() į žinučių paketus. Kadangi viskas Kafka yra orientuota į paketą, ji iš tikrųjų gana gerai veikia daugeliu atvejų ir yra naudinga priemonė vartotojams, kuriems reikia labai tvirtų garantijų. Didžioji dalis gryno Kafkos veikimo atsiranda dėl pranešimų, kurie siunčiami brokeriui kaip paketai ir kad šie pranešimai iš tarpininko skaitomi nuosekliais blokais naudojant nulis kopijos operacijos (operacijos, kurių metu neatliekama duomenų kopijavimo užduotis iš vienos atminties srities į kitą). Pastarasis yra didelis našumo ir išteklių padidėjimas ir įmanomas tik naudojant pagrindinę žurnalo duomenų struktūrą, kuri apibrėžia skaidinių schemą.

„Kafka“ klasteryje galimas daug geresnis našumas nei naudojant vieną „Kafka“ brokerį, nes temų skaidiniai gali išsiplėsti daugelyje atskirų įrenginių.

rezultatai

Šiame skyriuje apžvelgėme, kaip Kafka architektūra iš naujo įsivaizduoja klientų ir brokerių santykius, kad būtų sukurtas neįtikėtinai tvirtas pranešimų siuntimo vamzdynas, kurio pralaidumas daug kartų didesnis nei įprasto pranešimų tarpininko. Aptarėme funkcionalumą, kurį jis naudoja tam pasiekti, ir trumpai apžvelgėme šią funkciją teikiančių programų architektūrą. Kitame skyriuje apžvelgsime dažniausiai pasitaikančias problemas, kurias turi išspręsti pranešimų siuntimo programos, ir aptarsime jų sprendimo strategijas. Baigsime skyrių aprašydami, kaip kalbėti apie pranešimų technologijas apskritai, kad galėtumėte įvertinti jų tinkamumą jūsų naudojimo atvejams.

Ankstesnė išversta dalis: Suprasti pranešimų brokerius. Mokytis susirašinėjimo su ActiveMQ ir Kafka mechanikos. 1 skyrius

Vertimas atliktas: tele.gg/middle_java

Turi būti tęsiama ...

Apklausoje gali dalyvauti tik registruoti vartotojai. Prisijungti, Prašau.

Ar Kafka naudojama jūsų organizacijoje?

  • Taip

  • Ne

  • Anksčiau naudotas, dabar ne

  • Planuojame naudoti

Balsavo 38 vartotojų. 8 vartotojai susilaikė.

Šaltinis: www.habr.com

Добавить комментарий