Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka

Jatkoa pienen kirjan käännökselle:
Viestivälittäjien ymmärtäminen
kirjoittaja: Jakub Korab, kustantaja: O'Reilly Media, Inc., julkaisupäivä: kesäkuu 2017, ISBN: 9781492049296.

Edellinen käännetty osa: Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 1 Johdanto

LUKU 3

Kafka

Kafka kehitettiin LinkedInissä kiertämään joitakin perinteisten viestivälittäjien rajoituksia ja välttämään useiden viestivälittäjien perustamista erilaisiin point-to-point-vuorovaikutuksiin, mikä on kuvattu tämän kirjan kohdassa "Skaalaus ylös ja pois" sivulla 28. Käyttötapaukset LinkedIn on suurelta osin tukeutunut erittäin suurten tietomäärien, kuten sivujen napsautusten ja käyttölokien, yksisuuntaiseen käsittelyyn, mutta silti sallinut näiden tietojen käytön useissa järjestelmissä vaikuttamatta tuottajien tai muiden kuluttajien tuottavuuteen. Itse asiassa syy Kafkan olemassaoloon on saada sellainen viestinvälitysarkkitehtuuri, jota Universal Data Pipeline kuvaa.

Tämän perimmäisen tavoitteen vuoksi syntyi luonnollisesti muita vaatimuksia. Kafkan pitäisi:

  • Ole erittäin nopea
  • Tarjoa enemmän kaistanleveyttä, kun käsittelet viestejä
  • Tukee Publisher-Subscriber- ja Point-to-Point-malleja
  • Älä hidasta kuluttajien lisäämistä. Esimerkiksi sekä jonon että aiheen suorituskyky heikkenee ActiveMQ:ssa, kun määränpäässä olevien kuluttajien määrä kasvaa.
  • olla vaakasuunnassa skaalautuva; jos yksi välittäjä, joka jatkaa viestejä, voi tehdä sen vain levyn suurimmalla nopeudella, on järkevää ylittää yksittäisen välittäjän esiintymän suorituskyvyn parantamiseksi
  • Rajoita pääsyä viestien tallentamiseen ja uudelleenhakuun

Kaiken tämän saavuttamiseksi Kafka otti käyttöön arkkitehtuurin, joka määritteli uudelleen asiakkaiden ja viestintävälittäjien roolit ja vastuut. JMS-malli on hyvin välittäjäkeskeinen, jossa välittäjä vastaa viestien jakelusta ja asiakkaiden tarvitsee huolehtia vain viestien lähettämisestä ja vastaanottamisesta. Kafka puolestaan ​​on asiakaslähtöinen, ja asiakas ottaa vastaan ​​monia perinteisen välittäjän ominaisuuksia, kuten asiaankuuluvien viestien oikeudenmukaisen jakelun kuluttajille, vastineeksi erittäin nopeasta ja skaalautuvasta välittäjästä. Perinteisten viestintäjärjestelmien parissa työskennelleiltä Kafkan kanssa työskentely edellyttää perusteellista mielenmuutosta.
Tämä suunnittelusuunta on johtanut viestintäinfrastruktuurin luomiseen, joka pystyy lisäämään suorituskykyä useilla suuruusluokilla verrattuna perinteiseen välittäjään. Kuten näemme, tämä lähestymistapa sisältää kompromisseja, mikä tarkoittaa, että Kafka ei sovellu tietyntyyppisiin työkuormiin ja asennettuihin ohjelmistoihin.

Yhtenäinen kohdemalli

Täyttääkseen yllä kuvatut vaatimukset Kafka on yhdistänyt julkaisu-tilaa- ja point-to-point -viestintätoiminnot yhdentyyppiseen kohteeseen. aihe. Tämä on hämmentävää ihmisille, jotka ovat työskennelleet viestintäjärjestelmien kanssa, joissa sana "aihe" viittaa lähetysmekanismiin, josta (aiheesta) lukeminen on kestämätöntä. Kafka-aiheita tulee pitää hybridikohteena, kuten tämän kirjan johdannossa on määritelty.

Tämän luvun loppuosan ajan, ellemme nimenomaisesti ilmoita toisin, termi "aihe" viittaa Kafka-aiheeseen.

Ymmärtääksemme täysin, miten aiheet käyttäytyvät ja mitä takeita ne tarjoavat, meidän on ensin tarkasteltava, kuinka ne toteutetaan Kafkassa.
Jokaisella Kafkan aiheella on oma lokinsa.
Kafkalle viestejä lähettävät tuottajat kirjoittavat tähän lokiin, ja kuluttajat lukevat lokista jatkuvasti eteenpäin siirtyvien osoittimien avulla. Kafka poistaa ajoittain lokin vanhimmat osat riippumatta siitä, onko näiden osien viestit luettu vai ei. Keskeinen osa Kafkan suunnittelua on, että välittäjä ei välitä luetaanko viestejä vai ei – se on asiakkaan vastuulla.

Termit "loki" ja "osoitin" eivät näy Kafka dokumentaatio. Näitä tunnettuja termejä käytetään tässä ymmärtämisen helpottamiseksi.

Tämä malli eroaa täysin ActiveMQ:sta, jossa kaikkien jonojen viestit tallennetaan samaan lokiin ja välittäjä merkitsee viestit poistetuiksi niiden lukemisen jälkeen.
Kaivataan nyt hieman syvemmälle ja katsotaan aihelokia tarkemmin.
Kafka-loki koostuu useista osioista (Kuva 3-1). Kafka takaa tiukan järjestyksen jokaisessa osiossa. Tämä tarkoittaa, että osioon tietyssä järjestyksessä kirjoitetut viestit luetaan samassa järjestyksessä. Jokainen osio toteutetaan rullaavana lokitiedostona, joka sisältää osajoukko (osajoukko) kaikista sen tuottajien aiheeseen lähettämistä viesteistä. Luotu aihe sisältää oletusarvoisesti yhden osion. Osioiden idea on Kafkan keskeinen ajatus vaakasuoraan skaalaukseen.

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-1. Kafka väliseinät

Kun tuottaja lähettää viestin Kafka-aiheeseen, hän päättää, mihin osioon viesti lähetetään. Tarkastelemme tätä myöhemmin tarkemmin.

Viestien lukeminen

Asiakas, joka haluaa lukea viestejä, hallitsee nimettyä osoitinta nimeltä kuluttajaryhmä, mikä viittaa offset viestit osiossa. Siirtymä on inkrementaalinen sijainti, joka alkaa 0:sta osion alussa. Tämä kuluttajaryhmä, johon viitataan API:ssa käyttäjän määrittämän group_id:n kautta, vastaa yksi looginen kuluttaja tai järjestelmä.

Useimmat viestintäjärjestelmät lukevat dataa kohteesta useiden esiintymien ja säikeiden avulla viestien käsittelemiseksi rinnakkain. Näin ollen on yleensä useita kuluttaja-ilmentymiä, jotka jakavat saman kuluttajaryhmän.

Lukemisen ongelma voidaan esittää seuraavasti:

  • Aiheessa on useita osioita
  • Useat kuluttajaryhmät voivat käyttää aihetta samanaikaisesti
  • Kuluttajaryhmällä voi olla useita erillisiä esiintymiä

Tämä on ei-triviaali monista moneen -ongelma. Ymmärtääksemme, kuinka Kafka käsittelee kuluttajaryhmien, kuluttaja-ilmentymien ja osioiden välisiä suhteita, katsotaanpa sarjaa asteittain monimutkaisempia lukuskenaarioita.

Kuluttajat ja kuluttajaryhmät

Otetaan lähtökohtana aihe, jossa on yksi osio (Kuva 3-2).

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-2. Kuluttaja lukee osiolta

Kun kuluttajailmentymä muodostaa yhteyden omalla group_id-tunnistellaan tähän aiheeseen, sille määritetään lukuosio ja siirtymä kyseisessä osiossa. Tämän poikkeaman sijainti on konfiguroitavissa asiakkaassa osoittimena viimeisimpään sijaintiin (uusin viesti) tai aikaisimpaan sijaintiin (vanhin viesti). Kuluttaja pyytää (kyselyitä) viestejä aiheesta, jolloin ne luetaan peräkkäin lokista.
Offset-positio sitoutuu säännöllisesti takaisin Kafkaan ja tallennetaan viesteinä sisäiseen aiheeseen _consumer_offsets. Luettuja viestejä ei edelleenkään poisteta, toisin kuin tavallinen välittäjä, ja asiakas voi kelata siirtoa taaksepäin käsitelläkseen jo katsotut viestit uudelleen.

Kun toinen looginen kuluttaja muodostaa yhteyden käyttämällä eri ryhmätunnusta, se hallitsee toista osoitinta, joka on riippumaton ensimmäisestä (Kuva 3-3). Siten Kafka-aihe toimii jonona, jossa on yksi kuluttaja, ja kuten tavallinen julkaisu-tilaa (pub-sub) -aihe, jonka tilaavat useat kuluttajat, lisäetuna, että kaikki viestit tallennetaan ja niitä voidaan käsitellä useita kertoja.

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-3. Kaksi kuluttajaa eri kuluttajaryhmissä lukee samasta osiosta

Kuluttajat kuluttajaryhmässä

Kun yksi kuluttaja-ilmentymä lukee tietoja osiosta, se hallitsee täysin osoitinta ja käsittelee viestejä edellisessä osiossa kuvatulla tavalla.
Jos useita kuluttajaesiintymiä yhdistettiin samalla group_id:llä aiheeseen yhdellä osiolla, viimeksi yhdistänyt ilmentymä saa osoittimen hallinnan ja siitä hetkestä lähtien se vastaanottaa kaikki viestit (Kuva 3-4).

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-4. Kaksi kuluttajaa samassa kuluttajaryhmässä lukee samasta osiosta

Tätä käsittelytapaa, jossa kuluttajainstanssien määrä ylittää osioiden lukumäärän, voidaan ajatella eräänlaisena yksinomaisena kuluttajana. Tämä voi olla hyödyllistä, jos tarvitset kuluttajainstanssien "aktiivinen-passiivinen" (tai "kuuma-lämmin") klusterointia, vaikka useiden kuluttajien ajaminen rinnakkain ("aktiivinen-aktiivinen" tai "kuuma-kuuma") on paljon tyypillisempää kuin valmiustilassa.

Tämä yllä kuvattu viestin jakelukäyttäytyminen voi olla yllättävää verrattuna siihen, miten normaali JMS-jono käyttäytyy. Tässä mallissa jonoon lähetettävät viestit jakautuvat tasaisesti kahden kuluttajan kesken.

Useimmiten, kun luomme useita kuluttajia, teemme tämän joko käsitelläksemme viestejä rinnakkain tai lisätäksemme lukunopeutta tai lisätäksemme lukuprosessin vakautta. Koska vain yksi kuluttajaesiintymä voi lukea tietoja osiolta kerrallaan, miten tämä saavutetaan Kafkassa?

Yksi tapa tehdä tämä on käyttää yhtä kuluttajaesiintymää lukemaan kaikki viestit ja välittämään ne säiepooliin. Vaikka tämä lähestymistapa lisää käsittelyn suorituskykyä, se lisää kuluttajalogiikan monimutkaisuutta eikä lisää lukujärjestelmän kestävyyttä. Jos yksi kuluttajan kopio katoaa sähkökatkon tai vastaavan tapahtuman vuoksi, vähennys pysähtyy.

Kanoninen tapa ratkaista tämä ongelma Kafkassa on käyttää bОlisää osioita.

Osiointi

Osiot ovat tärkein mekanismi aiheen lukemisen ja skaalauksen rinnakkaisemiseksi yhden välittäjän kaistanleveyden yli. Tämän ymmärtämiseksi paremmin harkitaan tilannetta, jossa on aihe, jossa on kaksi osiota ja yksi kuluttaja tilaa tämän aiheen (Kuva 3-5).

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-5. Yksi kuluttaja lukee useista osioista

Tässä skenaariossa kuluttaja saa hallinnan osoittimia, jotka vastaavat sen group_id-tunnusta molemmissa osioissa, ja hän alkaa lukea viestejä molemmista osioista.
Kun tähän aiheeseen lisätään ylimääräinen kuluttaja samalle ryhmätunnukselle, Kafka jakaa uudelleen yhden osioista ensimmäiseltä kuluttajalle toiselle. Tämän jälkeen jokainen kuluttajan esiintymä lukee yhdestä aiheen osiosta (Kuva 3-6).

Varmistaaksesi, että viestejä käsitellään rinnakkain 20 säikeessä, tarvitset vähintään 20 osiota. Jos osioita on vähemmän, jää kuluttajien pariin, joilla ei ole mitään työstettävää, kuten aiemmin on kuvattu eksklusiivisia kuluttajia koskevassa keskustelussa.

Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 3. Kafka
Kuva 3-6. Kaksi kuluttajaa samassa kuluttajaryhmässä lukee eri osioista

Tämä menetelmä vähentää huomattavasti Kafka-välittäjän monimutkaisuutta verrattuna JMS-jonon ylläpitämiseen vaadittavaan viestien jakeluun. Täällä sinun ei tarvitse huolehtia seuraavista seikoista:

  • Kenen kuluttajan pitäisi vastaanottaa seuraava viesti, joka perustuu kiertoroin-allokaatioon, esihakupuskureiden nykyiseen kapasiteetiin tai aikaisempiin viesteihin (kuten JMS-viestiryhmien kohdalla).
  • Mitä viestejä mille kuluttajille lähetetään ja pitäisikö ne toimittaa uudelleen, jos ne epäonnistuvat.

Kafkan välittäjän tarvitsee vain välittää viestejä peräkkäin kuluttajalle, kun tämä pyytää niitä.

Vaatimukset oikolukujen rinnakkaisuudelle ja epäonnistuneiden viestien uudelleenlähettämiselle eivät kuitenkaan katoa – vastuu niistä siirtyy välittäjältä asiakkaalle. Tämä tarkoittaa, että ne on otettava huomioon koodissasi.

Viestien lähettäminen

Viestin tuottajan vastuulla on päättää, mihin osioon viesti lähetetään. Ymmärtääksemme mekanismin, jolla tämä tehdään, meidän on ensin pohdittava, mitä tarkalleen ottaen lähetämme.

Kun JMS:ssä käytämme viestirakennetta, jossa on metatiedot (otsikot ja ominaisuudet) ja runko, joka sisältää hyötykuorman (payload), kun taas Kafkassa viesti on pari "avainarvo". Viestin hyötykuorma lähetetään arvona. Avainta sitä vastoin käytetään pääasiassa osiointiin ja sen täytyy sisältää liikelogiikkakohtainen avainlaittaaksesi liittyvät viestit samaan osioon.

Luvussa 2 käsittelimme online-vedonlyöntitilannetta, jossa yksittäisen kuluttajan on käsiteltävä toisiinsa liittyvät tapahtumat järjestyksessä:

  1. Käyttäjätili on määritetty.
  2. Rahat hyvitetään tilille.
  3. Panostetaan, joka nostaa rahaa tililtä.

Jos jokainen tapahtuma on aiheeseen lähetetty viesti, luonnollinen avain on tilin tunnus.
Kun viesti lähetetään Kafka Producer API:lla, se välitetään osiofunktiolle, joka viestin ja Kafka-klusterin nykyisen tilan perusteella palauttaa sen osion tunnuksen, johon viesti tulee lähettää. Tämä ominaisuus on toteutettu Javassa Partitioner-rajapinnan kautta.

Tämä käyttöliittymä näyttää tältä:

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

Partitioner-toteutus käyttää oletusarvoista yleiskäyttöistä tiivistysalgoritmia avaimen päällä osion määrittämiseen tai round-robin-menetelmää, jos avainta ei ole määritetty. Tämä oletusarvo toimii hyvin useimmissa tapauksissa. Haluat kuitenkin jatkossa kirjoittaa omasi.

Oman osiointistrategian kirjoittaminen

Katsotaanpa esimerkkiä, jossa haluat lähettää metatiedot viestin hyötykuorman mukana. Hyötykuorma esimerkissämme on ohje talletuksen tekemiseen pelitilille. Ohje on jotain, jota haluamme taatusti, ettei sitä muuteta lähetyksen aikana, ja haluamme olla varmoja, että vain luotettava ylävirran järjestelmä voi aloittaa kyseisen käskyn. Tällöin lähettävä ja vastaanottava järjestelmä sopivat allekirjoituksen käytöstä viestin todentamiseksi.
Normaalissa JMS:ssä määritämme yksinkertaisesti "viestin allekirjoitus" -ominaisuuden ja lisäämme sen viestiin. Kafka ei kuitenkaan tarjoa meille mekanismia metatietojen välittämiseen, vain avaimen ja arvon.

Koska arvo on pankkisiirron hyötykuorma, jonka eheyden haluamme säilyttää, meillä ei ole muuta vaihtoehtoa kuin määritellä avaimessa käytettävä tietorakenne. Olettaen, että tarvitsemme tilitunnuksen osiointiin, koska kaikki tiliin liittyvät viestit on käsiteltävä järjestyksessä, saamme aikaan seuraavan JSON-rakenteen:

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

Koska allekirjoituksen arvo vaihtelee hyötykuorman mukaan, Partitioner-rajapinnan oletushajautusstrategia ei ryhmittele luotettavasti liittyviä viestejä. Siksi meidän on kirjoitettava oma strategiamme, joka jäsentää tämän avaimen ja osittaa accountId-arvon.

Kafka sisältää tarkistussummat myymälässä olevien viestien vioittumisen havaitsemiseksi, ja siinä on täysi joukko turvaominaisuuksia. Siitä huolimatta toimialakohtaisia ​​vaatimuksia, kuten yllä oleva, ilmenee joskus.

Käyttäjän osiointistrategian on varmistettava, että kaikki liittyvät viestit päätyvät samaan osioon. Vaikka tämä vaikuttaa yksinkertaiselta, vaatimusta voi monimutkaistaa liittyvien viestien järjestämisen tärkeys ja se, kuinka kiinteää aiheen osioiden määrä on.

Aiheen osioiden määrä voi muuttua ajan myötä, koska niitä voidaan lisätä, jos liikenne ylittää alkuperäiset odotukset. Siten sanomaavaimet voidaan liittää osioon, johon ne alun perin lähetettiin, mikä tarkoittaa, että tilaa jaetaan tuottajainstanssien välillä.

Toinen huomioon otettava tekijä on viestien tasainen jakautuminen osioiden välillä. Tyypillisesti avaimia ei jaeta tasaisesti viesteihin, eivätkä hajautustoiminnot takaa viestien tasapuolista jakautumista pienelle avainjoukolle.
On tärkeää huomata, että vaikka päätätkin jakaa viestit, itse erotin on ehkä käytettävä uudelleen.

Harkitse vaatimusta replikoida tietoja Kafka-klusterien välillä eri maantieteellisissä paikoissa. Tätä tarkoitusta varten Kafkan mukana tulee MirrorMaker-niminen komentorivityökalu, jota käytetään viestien lukemiseen klusterista ja siirtämiseen toiseen.

MirrorMakerin on ymmärrettävä replikoidun aiheen avaimet säilyttääkseen suhteellisen järjestyksen sanomien välillä replikoitaessa klusterien välillä, koska kyseisen aiheen osioiden määrä ei välttämättä ole sama kahdessa klusterissa.

Mukautetut osiointistrategiat ovat suhteellisen harvinaisia, koska oletushajautus tai round robin toimii hyvin useimmissa skenaarioissa. Jos kuitenkin tarvitset vahvoja tilaustakuita tai haluat poimia metatietoja hyötykuormista, osiointi on asia, jota sinun tulee tarkastella lähemmin.

Kafkan skaalautuvuuden ja suorituskyvyn edut tulevat siirtämällä osa perinteisen välittäjän tehtävistä asiakkaalle. Tällöin päätetään jakaa mahdollisesti asiaan liittyvät viestit useiden rinnakkaisten kuluttajien kesken.

JMS-välittäjien on myös käsiteltävä tällaisia ​​​​vaatimuksia. Mielenkiintoista on, että JMS-viestiryhmien kautta toteutettu mekanismi aiheeseen liittyvien viestien lähettämiseksi samalle kuluttajalle (muunnelma sticky load balancing (SLB) -strategiasta) edellyttää myös, että lähettäjä merkitsee viestit liittyviksi. JMS:n tapauksessa välittäjä on vastuussa tämän viestiryhmän lähettämisestä yhdelle kuluttajalle monista ja ryhmän omistajuuden siirtämisestä, jos kuluttaja kaatuu.

Tuottajasopimukset

Osiointi ei ole ainoa huomioitava asia viestejä lähetettäessä. Tarkastellaan Java API:n Producer-luokan send()-menetelmiä:

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

On heti huomattava, että molemmat menetelmät palauttavat Future, mikä osoittaa, että lähetystoimintoa ei suoriteta heti. Tuloksena on, että viesti (ProducerRecord) kirjoitetaan kunkin aktiivisen osion lähetyspuskuriin ja lähetetään välittäjälle taustasäikeenä Kafka-asiakaskirjastossa. Vaikka tämä tekee asioista uskomattoman nopeita, se tarkoittaa, että kokematon sovellus voi menettää viestejä, jos sen prosessi pysäytetään.

Kuten aina, on olemassa tapa tehdä lähetystoiminnasta luotettavampi suorituskyvyn kustannuksella. Tämän puskurin kooksi voidaan asettaa 0, ja lähettävän sovelluksen säiettä on pakko odottaa, kunnes viestin siirto välittäjälle on valmis, seuraavasti:

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

Lisää viestien lukemisesta

Viestien lukemiseen liittyy lisää monimutkaisia ​​asioita, joita on syytä spekuloida. Toisin kuin JMS API, joka voi ajaa viestikuuntelijan vastauksena viestiin, Kuluttaja Kafka vain äänestää. Tarkastellaanpa menetelmää tarkemmin kysely ()käytetään tähän tarkoitukseen:

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

Metodin palautusarvo on useita objekteja sisältävä säiliörakenne kuluttajaennätys mahdollisesti useista osioista. kuluttajaennätys on itse haltijaobjekti avain-arvo-parille, johon liittyy metatietoja, kuten osio, josta se on johdettu.

Kuten luvussa 2 on todettu, meidän on pidettävä mielessä, mitä viesteille tapahtuu sen jälkeen, kun ne on käsitelty onnistuneesti tai epäonnistuneesti, esimerkiksi jos asiakas ei pysty käsittelemään viestiä tai jos se keskeytyy. JMS:ssä tämä käsiteltiin kuittaustilassa. Välittäjä joko poistaa onnistuneesti käsitellyn viestin tai toimittaa raaka- tai väärennetyn viestin uudelleen (olettaen, että tapahtumia käytettiin).
Kafka toimii hyvin eri tavalla. Viestejä ei poisteta välittäjästä oikolukemisen jälkeen, ja se, mitä tapahtuu epäonnistuessa, on itse oikoluentakoodin vastuulla.

Kuten olemme sanoneet, kuluttajaryhmä liittyy lokin offsetiin. Tähän siirtymään liittyvä lokin sijainti vastaa seuraavaa vastauksena lähetettävää viestiä kysely (). Ajankohta, jolloin tämä siirtymä kasvaa, on lukemisen kannalta ratkaiseva.

Palatakseni aiemmin käsiteltyyn lukumalliin sanomankäsittely koostuu kolmesta vaiheesta:

  1. Hae viesti luettavaksi.
  2. Käsittele viesti.
  3. Vahvista viesti.

Kafka-kuluttajassa on konfigurointivaihtoehto enable.auto.commit. Tämä on usein käytetty oletusasetus, kuten yleistä sanan "auto" sisältäville asetuksille.

Ennen Kafka 0.10:tä tätä vaihtoehtoa käyttävä asiakas lähetti viimeisen luetun viestin offsetin seuraavassa puhelussa kysely () käsittelyn jälkeen. Tämä tarkoitti, että kaikki jo haetut viestit voitiin käsitellä uudelleen, jos asiakas oli jo käsitellyt ne, mutta tuhoutui odottamatta ennen soittamista kysely (). Koska välittäjällä ei ole tietoa siitä, kuinka monta kertaa viesti on luettu, seuraava viestin hakeva kuluttaja ei tiedä, että mitään pahaa on tapahtunut. Tämä käyttäytyminen oli näennäistapahtumaa. Poikkeus tapahtui vain, jos viesti oli käsitelty onnistuneesti, mutta jos asiakas keskeytyi, välittäjä lähettää saman viestin uudelleen toiselle asiakkaalle. Tämä käyttäytyminen oli yhdenmukainen viestin toimitustakuun kanssa "ainakin kerran".

Kafka 0.10:ssa asiakaskoodia on muutettu niin, että asiakaskirjasto laukaisee toimituksen määräajoin määrityksen mukaisesti auto.commit.interval.ms. Tämä toiminta on jossain JMS AUTO_ACKNOWLEDGE- ja DUPS_OK_ACKNOWLEDGE-tilojen välissä. Automaattista toimitusta käytettäessä viestit voitiin sitoutua riippumatta siitä, onko ne todella käsitelty - tämä voi tapahtua hitaalla kuluttajalla. Jos kuluttaja keskeyttää, viestit hakisi seuraava kuluttaja aloittaen sitoutuneesta paikasta, mikä voi johtaa viestin ohittamiseen. Tässä tapauksessa Kafka ei menettänyt viestejä, lukukoodi ei vain käsitellyt niitä.

Tässä tilassa on sama lupaus kuin versiossa 0.9: viestejä voidaan käsitellä, mutta jos se epäonnistuu, siirtymää ei ehkä tehdä, mikä saattaa aiheuttaa toimituksen kaksinkertaistumisen. Mitä enemmän viestejä haet suorituksen aikana kysely (), sitä enemmän tämä ongelma.

Kuten kohdassa "Viestien lukeminen jonosta" sivulla 21 on kerrottu, viestin kertaluonteista toimitusta ei ole olemassa sanomanvälitysjärjestelmässä, kun vikatilat otetaan huomioon.

Kafkassa on kaksi tapaa sitoa (commit) offset (offset): automaattisesti ja manuaalisesti. Molemmissa tapauksissa viestejä voidaan käsitellä useita kertoja, jos viesti käsiteltiin mutta epäonnistui ennen toimitusta. Voit myös päättää olla käsittelemättä viestiä ollenkaan, jos toimitus tapahtui taustalla ja koodisi valmistui ennen kuin se pystyi käsittelemään (ehkä Kafka 0.9:ssa ja sitä aikaisemmissa).

Voit ohjata manuaalista offset-todennusprosessia Kafka-kuluttajasovellusliittymässä asettamalla parametrin enable.auto.commit vääräksi ja kutsuu nimenomaan jotakin seuraavista menetelmistä:

void commitSync();
void commitAsync();

Jos haluat käsitellä viestin "vähintään kerran", sinun on suoritettava offset manuaalisesti commitSync()suorittamalla tämän komennon välittömästi viestien käsittelyn jälkeen.

Nämä menetelmät eivät salli viestien kuittaamista ennen niiden käsittelyä, mutta ne eivät poista mahdollisia käsittelyviiveitä samalla, kun ne antavat vaikutelman tapahtumista. Kafkassa ei ole liiketoimia. Asiakas ei voi tehdä seuraavia asioita:

  • Peruuta väärennetty viesti automaattisesti. Kuluttajien tulee itse käsitellä ongelmallisista hyötykuormista ja taustakatkoksista aiheutuvia poikkeuksia, koska he eivät voi luottaa välittäjään viestien uudelleen toimittamiseen.
  • Lähetä viestejä useisiin aiheisiin yhdellä atomioperaatiolla. Kuten pian näemme, eri aiheiden ja osioiden hallinta voi sijaita Kafka-klusterin eri koneissa, jotka eivät koordinoi tapahtumia lähetettäessä. Tätä kirjoitettaessa on tehty jonkin verran työtä tämän mahdollistamiseksi KIP-98:n kanssa.
  • Yhdistä yhden viestin lukeminen yhdestä aiheesta toisen viestin lähettämiseen toiseen aiheeseen. Kafka-arkkitehtuuri on jälleen riippuvainen useista itsenäisistä koneista, jotka toimivat yhtenä väylänä, eikä tätä yritetä piilottaa. Ei esimerkiksi ole API-komponentteja, jotka mahdollistaisivat linkittämisen kuluttaja и tuottaja kaupassa. JMS:ssä tämän tarjoaa objekti istuntojoista luodaan MessageProducers и MessageConsumers.

Jos emme voi luottaa tapahtumiin, kuinka voimme tarjota semantiikan, joka on lähempänä perinteisten viestintäjärjestelmien tarjoamaa semantiikkaa?

Jos on mahdollista, että kuluttajan kompensaatio voi kasvaa ennen kuin viesti on käsitelty, esimerkiksi kuluttajan kaatuessa, kuluttajalla ei ole mahdollisuutta tietää, onko hänen kuluttajaryhmänsä missannut viestin, kun sille osoitetaan osio. Joten yksi strategia on kelata siirtymä taaksepäin edelliseen kohtaan. Kafka-kuluttajasovellusliittymä tarjoaa tähän seuraavat menetelmät:

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

menetelmä etsi () voidaan käyttää menetelmän kanssa
offsetsFor Times (Kartta aikaleimatHakuun) kelata takaisin johonkin tiettyyn menneisyyden ajankohtaan.

Epäsuorasti tämän lähestymistavan käyttö tarkoittaa, että on erittäin todennäköistä, että jotkin aiemmin käsitellyt viestit luetaan ja käsitellään uudelleen. Tämän välttämiseksi voimme käyttää idempotenttia lukemista, kuten luvussa 4 on kuvattu, jotta voimme pitää kirjaa aiemmin katsotuista viesteistä ja poistaa kaksoiskappaleet.

Vaihtoehtoisesti kuluttajakoodi voidaan pitää yksinkertaisena, kunhan viestin katoaminen tai kopioiminen on hyväksyttävää. Kun tarkastelemme Kafkaa yleisesti käytettyjä käyttötapauksia, kuten lokitapahtumien käsittelyä, mittareita, napsautusten seurantaa jne., ymmärrämme, että yksittäisten viestien katoamisella ei todennäköisesti ole merkittävää vaikutusta ympäröiviin sovelluksiin. Tällaisissa tapauksissa oletusarvot ovat täysin hyväksyttäviä. Toisaalta, jos hakemuksesi tarvitsee lähettää maksuja, sinun on huolehdittava huolellisesti jokaisesta yksittäisestä viestistä. Kaikki riippuu kontekstista.

Henkilökohtaiset havainnot osoittavat, että kun viestien intensiteetti kasvaa, jokaisen yksittäisen viestin arvo pienenee. Suuret viestit ovat yleensä arvokkaita, kun niitä tarkastellaan koostetussa muodossa.

Korkea saatavuus

Kafkan lähestymistapa korkeaan käytettävyyteen on hyvin erilainen kuin ActiveMQ:n lähestymistapa. Kafka on suunniteltu skaalattavien klustereiden ympärille, joissa kaikki välittäjät vastaanottavat ja jakavat viestejä samaan aikaan.

Kafka-klusteri koostuu useista välittäjäilmentymistä, jotka toimivat eri palvelimilla. Kafka on suunniteltu toimimaan tavallisella erillisellä laitteistolla, jossa jokaisella solmulla on oma tallennustila. Verkkoon liitetyn tallennustilan (SAN) käyttöä ei suositella, koska useat laskentasolmut voivat kilpailla ajasta.Ыe tallennusvälit ja luoda ristiriitoja.

Kafka on aina päällä järjestelmä. Monet suuret Kafka-käyttäjät eivät koskaan sammuta klustereitaan, ja ohjelmisto päivittyy aina peräkkäisellä uudelleenkäynnistyksellä. Tämä saavutetaan takaamalla yhteensopivuus edellisen version kanssa välittäjien välisille viesteille ja vuorovaikutuksille.

Palvelinklusteriin yhdistetyt välittäjät ZooKeeper, joka toimii konfigurointitietorekisterinä ja jota käytetään koordinoimaan kunkin välittäjän rooleja. ZooKeeper itsessään on hajautettu järjestelmä, joka tarjoaa korkean käytettävyyden replikoimalla tietoja perustamalla päätösvaltainen.

Perustapauksessa aihe luodaan Kafka-klusteriin, jolla on seuraavat ominaisuudet:

  • Osioiden määrä. Kuten aiemmin mainittiin, tässä käytetty tarkka arvo riippuu halutusta rinnakkaislukemisen tasosta.
  • Replikointikerroin (tekijä) määrittää, kuinka monen klusterin välittäjän esiintymän tulee sisältää tämän osion lokit.

ZooKeepersin avulla Kafka yrittää jakaa oikeudenmukaisesti uudet osiot klusterin välittäjien kesken. Tämän tekee yksi esiintymä, joka toimii ohjaimena.

Ajon aikana jokaiselle aihealueelle ohjain jakaa rooleja välittäjälle johtaja (johtaja, mestari, juontaja) ja seuraajia (seuraajat, orjat, alaiset). Välittäjä, joka toimii tämän osion johtajana, on vastuussa kaikkien tuottajien sille lähettämien viestien vastaanottamisesta ja viestien jakamisesta kuluttajille. Kun viestit lähetetään aiheosioon, ne replikoidaan kaikkiin välittäjäsolmuihin, jotka toimivat kyseisen osion seuraajina. Kutakin osion lokit sisältävä solmu kutsutaan kopio. Välittäjä voi toimia joidenkin osioiden johtajana ja toisten seuraajana.

Kutsutaan seuraaja, joka sisältää kaikki johtajan viestit synkronoitu kopio (replika, joka on synkronoidussa tilassa, synkronoitu replika). Jos osion johtajana toimiva välittäjä kaatuu, mikä tahansa välittäjä, joka on ajan tasalla tai joka on synkronoitu kyseiselle osiolle, voi ottaa johtajan roolin. Se on uskomattoman kestävä muotoilu.

Parametri on osa tuottajan kokoonpanoa kuittaukset, joka määrittää, kuinka monen replikan on kuitattava (kuittattava) viestin vastaanottaminen ennen kuin sovellussäie jatkaa lähettämistä: 0, 1 tai kaikki. Jos asetettu kaikki, sitten kun viesti on vastaanotettu, johtaja lähettää vahvistuksen takaisin tuottajalle heti saatuaan vahvistuksia (kuittauksia) tietueelle useista aiheasetuksen määrittämistä vihjeistä (mukaan lukien häneltä itseltään). min.insync.replicas (oletus 1). Jos viestiä ei voida replikoida onnistuneesti, tuottaja heittää sovelluspoikkeuksen (NotEnoughReplicas tai NotEnoughReplicasAfterAppend).

Tyypillinen kokoonpano luo aiheen, jonka replikointikerroin on 3 (1 johtaja, 2 seuraajaa osiota kohti) ja parametrin min.insync.replicas on asetettu arvoon 2. Tässä tapauksessa klusteri sallii yhden topic-osiota hallitsevan välittäjän kaatua vaikuttamatta asiakassovelluksiin.

Tämä tuo meidät takaisin jo tuttuihin kompromissiin suorituskyvyn ja luotettavuuden välillä. Replikointi tapahtuu ylimääräisen odotusajan kustannuksella seuraajien vahvistuksille (kuittauksille). Vaikka replikointi ainakin kolmeen solmuun toimii rinnakkain, sen suorituskyky on sama kuin kahdessa (verkkokaistan käytön lisääntyminen huomioimatta).

Käyttämällä tätä replikointimallia Kafka välttää taitavasti jokaisen viestin fyysisen kirjoittamisen levylle toiminnolla sync(). Jokainen tuottajan lähettämä viesti kirjoitetaan osion lokiin, mutta kuten luvussa 2 on kerrottu, tiedostoon kirjoittaminen tapahtuu aluksi käyttöjärjestelmän puskurissa. Jos tämä viesti kopioidaan toiseen Kafka-instanssiin ja on sen muistissa, johtajan menetys ei tarkoita, että itse viesti olisi kadonnut - synkronoitu replika voi ottaa sen haltuunsa.
Leikkauksen suorittamisesta kieltäytyminen sync() tarkoittaa, että Kafka voi vastaanottaa viestejä yhtä nopeasti kuin se pystyy kirjoittamaan ne muistiin. Toisaalta, mitä kauemmin voit välttää muistin tyhjennyksen levylle, sitä parempi. Tästä syystä ei ole harvinaista, että Kafka-välittäjille osoitetaan 64 Gt tai enemmän muistia. Tämä muistin käyttö tarkoittaa, että yksi Kafka-instanssi voi helposti toimia useita tuhansia kertoja nopeammin kuin perinteinen viestivälittäjä.

Kafka voidaan myös määrittää käyttämään toimintoa sync() viestipaketteihin. Koska kaikki Kafkassa on pakettilähtöistä, se toimii itse asiassa varsin hyvin monissa käyttötapauksissa ja on hyödyllinen työkalu käyttäjille, jotka vaativat erittäin vahvoja takuita. Suuri osa Kafkan puhtaasta suorituskyvystä tulee viesteistä, jotka lähetetään välittäjälle paketteina ja että nämä viestit luetaan välittäjältä peräkkäisinä lohkoina käyttämällä nollakopio toiminnot (toiminnot, joiden aikana ei suoriteta tietojen kopiointia muistialueelta toiselle). Jälkimmäinen on suuri suorituskyky- ja resurssihyöty, ja se on mahdollista vain käyttämällä taustalla olevaa lokitietorakennetta, joka määrittää osiojärjestelmän.

Paljon parempi suorituskyky on mahdollista Kafka-klusterissa kuin yhdellä Kafka-välittäjällä, koska aiheosiot voivat skaalautua useisiin erillisiin koneisiin.

Tulokset

Tässä luvussa tarkastelimme, kuinka Kafka-arkkitehtuuri kuvittelee uudelleen asiakkaiden ja välittäjien välisen suhteen tarjotakseen uskomattoman vankan viestiketjun, jonka suorituskyky on monta kertaa suurempi kuin perinteisellä viestivälittäjällä. Olemme keskustelleet toiminnallisuuksista, joita se käyttää tämän saavuttamiseen, ja tarkastelimme lyhyesti tämän toiminnon tarjoavien sovellusten arkkitehtuuria. Seuraavassa luvussa tarkastellaan yleisiä ongelmia, joita viestintäpohjaisten sovellusten on ratkaistava, ja keskustellaan strategioista niiden käsittelemiseksi. Lopetamme luvun hahmottelemalla, miten viestintätekniikoista puhutaan yleisesti, jotta voit arvioida niiden soveltuvuutta käyttötapauksiin.

Edellinen käännetty osa: Viestien välittäjien ymmärtäminen. Viestintämekaniikan oppiminen ActiveMQ:n ja Kafkan avulla. Luku 1

Käännös tehty: tele.gg/middle_java

Jatkuu ...

Vain rekisteröityneet käyttäjät voivat osallistua kyselyyn. Kirjaudu sisään, ole kiltti.

Käytetäänkö Kafkaa organisaatiossasi?

  • Kyllä

  • Ei

  • Ennen käytetty, nyt ei

  • Aiomme käyttää

38 käyttäjää äänesti. 8 käyttäjää pidättyi äänestämästä.

Lähde: will.com

Lisää kommentti