Kafka en mikrotsjinsten: in oersjoch

Kafka en mikrotsjinsten: in oersjoch

Hoi allegearre. Yn dit artikel sil ik jo fertelle wêrom't wy by Avito keas Kafka njoggen moanne lyn en wat it is. Ik sil ien fan 'e gebrûksgefallen diele - in berjochtmakelaar. En as lêste, litte wy prate oer hokker foardielen wy krigen fan it brûken fan de Kafka as in tsjinst oanpak.

probleem

Kafka en mikrotsjinsten: in oersjoch

Earst, in bytsje kontekst. In skoft lyn begûnen wy fuort te gean fan monolityske arsjitektuer, en no hat Avito al ferskate hûnderten ferskillende tsjinsten. Se hawwe har eigen repositories, har eigen technologystapel en binne ferantwurdlik foar har diel fan 'e saaklike logika.

Ien fan 'e problemen mei in grut oantal tsjinsten is kommunikaasje. Tsjinst A wol faak ynformaasje witte dy't Tsjinst B hat. Yn dit gefal hat Tsjinst A tagong ta Tsjinst B fia in syngroane API. Tsjinst B wol witte wat der bart mei tsjinsten D en D, en se binne op har beurt ynteressearre yn tsjinsten A en B. As der in protte fan sokke "nijsgjirrige" tsjinsten binne, feroarje de ferbiningen dêrtusken in fergriemde tangel.

Tagelyk kin tsjinst A op elts momint net beskikber wurde. En wat moatte tsjinst B en alle oare tsjinsten dy't dêrmei ferbûn binne dwaan yn dit gefal? En as in keatling fan opfolgjende syngroane oproppen fereaske is om in saaklike operaasje te foltôgjen, wurdt de kâns op mislearring fan 'e hiele operaasje noch heger (en hoe langer de ketting, hoe heger it is).

Technology seleksje

Kafka en mikrotsjinsten: in oersjoch

Okee, de problemen binne dúdlik. Se kinne wurde eliminearre troch it meitsjen fan in sintralisearre messaging systeem tusken tsjinsten. No hoecht elk fan 'e tsjinsten allinich te witten oer dit messagingsysteem. Dêrneist moat it systeem sels fouttolerant en horizontaal skaalber wêze, en ek, yn gefal fan ûngemakken, in tagongsbuffer sammelje foar folgjende ferwurking.

Litte wy no de technology selektearje wêrop berjochtlevering sil wurde ymplementearre. Om dit te dwaan, litte wy earst begripe wat wy derfan ferwachtsje:

  • berjochten tusken tsjinsten moatte net ferlern gean;
  • berjochten kinne duplicated wurde;
  • berjochten kinne wurde opslein en lêzen op in djipte fan ferskate dagen (persistente buffer);
  • tsjinsten kinne abonnearje op de gegevens se binne ynteressearre yn;
  • meardere tsjinsten kinne lêze deselde gegevens;
  • berjochten kinne befetsje detaillearre, voluminous payload (evenemint-carried steat oerdracht);
  • Soms moatte jo de folchoarder fan berjochten garandearje.

It wie ek kritysk wichtich foar ús om it meast skalberber en betroubere systeem te kiezen mei hege trochslach (op syn minst 100k berjochten fan ferskate kilobytes per sekonde).

Op dit punt, wy seine ôfskie fan RabbitMQ (moeilik te hâlden stabyl op hege rps), PGQ út SkyTools (net fluch genôch en net skaal goed) en NSQ (net oanhâldend). Wy brûke al dizze technologyen yn ús bedriuw, mar se wiene net geskikt foar it probleem dat waard oplost.

Dêrnei begûnen wy te sjen nei technologyen dy't nij foar ús wiene - Apache Kafka, Apache Pulsar en NATS Streaming.

Pulsar wie de earste dy't ôfset waard. Wy besletten dat Kafka en Pulsar frij ferlykbere oplossingen binne. En nettsjinsteande it feit dat Pulsar is hifke troch grutte bedriuwen, is nijer en biedt legere latency (yn teory), wy besletten om ferlitte Kafka fan dizze twa as de de facto standert foar sokke taken. Wy sille wierskynlik weromkomme nei Apache Pulsar yn 'e takomst.

En no binne d'r twa kandidaten oer: NATS Streaming en Apache Kafka. Wy studearre beide oplossingen yn wat detail, en beide wiene geskikt foar de taak. Mar op it lêst wiene wy ​​bang foar de relative jeugd fan NATS Streaming (en it feit dat ien fan 'e wichtichste ûntwikkelders, Tyler Treat, besleat it projekt te ferlitten en syn eigen te begjinnen - Liftbridge). Tagelyk levere de Clustering-modus fan NATS Streaming net de mooglikheid fan sterke horizontale skaalfergrutting (wierskynlik is dit net langer in probleem nei de tafoeging fan 'e partitioneringsmodus yn 2017).

NATS Streaming is lykwols in koele technology skreaun yn Go en stipe troch de Cloud Native Computing Foundation. Oars as Apache Kafka, hat it Zookeeper net nedich om te wurkjen (miskien al gau kin itselde oer Kafka sein wurde), om't it RAFT yntern ymplementearret. Tagelyk is NATS Streaming makliker te behearjen. Wy slúte net út dat wy yn 'e takomst werom sille nei dizze technology.

En dochs, hjoed is ús winner Apache Kafka. Yn ús tests bliek it frij fluch te wêzen (mear as in miljoen berjochten per sekonde foar lêzen en skriuwen mei in berjochtvolume fan 1 kilobyte), frij betrouber, tige skalberber en bewiisd troch ûnderfining yn 'e produksje fan grutte bedriuwen. Derneist stipet Kafka op syn minst ferskate grutte kommersjele bedriuwen (wy brûke bygelyks de Confluent-ferzje), en Kafka hat ek in ûntwikkele ekosysteem.

Kafka oersjoch

Foardat wy begjinne, wol ik fuortendaliks in poerbêst boek oanbefelje - "Kafka: The Definitive Guide" (d'r is ek in Russyske oersetting, mar de termen binne in bytsje fernimmend). It befettet de ynformaasje dy't jo nedich hawwe om in basisbegryp fan Kafka te krijen en sels in bytsje mear. De dokumintaasje fan Apache en it blog fan Confluent binne ek goed skreaun en maklik te lêzen.

Litte wy dus in fûgelperspektiv nimme fan hoe't Kafka wurket. De basistopology fan Kafka bestiet út produsint, konsumint, makelder en bistetúnhâlder.

Broker

Kafka en mikrotsjinsten: in oersjoch

De makelder is ferantwurdlik foar it bewarjen fan jo gegevens. Alle gegevens wurde opslein yn binêre foarm, en de makelder wit net folle oer wat se binne en wat har struktuer is.

Elk logysk barrentype leit normaal yn in eigen apart ûnderwerp. Bygelyks, it evenemint fan it meitsjen fan in advertinsje kin falle yn it item.created ûnderwerp, en it barren fan syn feroaring kin falle yn item.changed. Underwerpen kinne wurde beskôge as evenemint klassifikaasje. Op it ûnderwerpnivo kinne jo konfiguraasjeparameters ynstelle lykas:

  • de hoemannichte gegevens opslein en / of har leeftyd (retention.bytes, retention.ms);
  • gegevens oerstallich faktor (replikaasje faktor);
  • maksimale grutte fan ien berjocht (max.message.bytes);
  • it minimum oantal konsekwinte replika's wêrby't gegevens nei in ûnderwerp skreaun wurde kinne (min.insync.replicas);
  • de mooglikheid om in failover út te fieren op in net-syngroane lagging replika mei potinsjele gegevensferlies (unclean.leader.election.enable);
  • en folle mear (https://kafka.apache.org/documentation/#topicconfigs).

Op syn beurt is elk ûnderwerp ferdield yn ien of mear partysjes. It is yn de partijen dat eveneminten úteinlik falle. As d'r mear as ien broker yn it kluster is, dan wurde de partysjes lykwichtich ferdield oer alle brokers (sa fier mooglik), wêrtroch't de lading op skriuwen en lêzen yn ien ûnderwerp yn ien kear op ferskate brokers skaal wurde kin.

Op skiif wurde gegevens foar elke partysje opslein yn 'e foarm fan segmentbestannen, standert gelyk oan ien gigabyte (bestjoerd troch log.segment.bytes). In wichtich skaaimerk is dat gegevens wurde wiske út partysjes (as behâld wurdt trigger) yn segminten (do kinst net wiskje ien evenemint út in partition, Jo kinne allinne wiskje in hiele segmint, en allinnich de ynaktyf).

Zoektocht

Zookeeper fungearret as in metadatawinkel en koördinator. It is hy dy't yn steat is om te fertellen oft makelders yn libben binne (jo kinne dit besjen troch de eagen fan dierenwachter mei zookeeper-shell mei it kommando ls /brokers/ids), hokker makelder de kontrôler is (get /controller), oft de partysjes yn syngronisaasje binne mei har replika's (get /brokers/topics/topic_name/partitions/partition_number/state). Ek is it nei bistetúnhâlder dat de produsint en konsumint earst geane om út te sykjen by hokker makelder hokker ûnderwerpen en partysjes opslein wurde. Yn gefallen dêr't in replikaasje faktor grutter as 1 wurdt oantsjutte foar in ûnderwerp, zookeeper sil oanjaan hokker partysjes binne de lieders (se wurde skreaun nei en lêzen út). Yn it gefal fan in makeldermislearring sil ynformaasje oer nije liederpartysjes wurde opnommen yn zookeeper (fan ferzje 1.1.0 asynchroan, en dat is wichtich).

Yn âldere ferzjes fan Kafka wie zookeeper ek ferantwurdlik foar it opslaan fan offsets, mar no wurde se opslein yn in spesjaal ûnderwerp __consumer_offsets op de makelder (hoewol't jo kinne noch brûke zookeeper foar dizze doelen).

De maklikste manier om jo gegevens yn in pompoen te feroarjen is om ynformaasje te ferliezen fan dierenwachter. Yn sa'n senario sil it heul lestich wêze om te begripen wat te lêzen en wêrfan.

Produsint

Produsint is meastentiids in tsjinst dy't direkt gegevens skriuwt nei Apache Kafka. De produsint selekteart in ûnderwerp wêryn hy syn ûnderwerpberjochten opslaan en begjint dêryn ynformaasje te skriuwen. Bygelyks, de produsint kin in advertinsjetsjinst wêze. Yn dit gefal sil it eveneminten stjoere lykas "advertinsje makke", "advertinsje bywurke", "advertinsje wiske", ensfh nei tematyske ûnderwerpen. Elk barren is in kaai-wearde-pear.

Standert wurde alle eveneminten ferdield ûnder ûnderwerppartysjes mei round-robin as de kaai net oantsjutte is (bestelling ferlieze), en fia MurmurHash (kaai) as de kaai oanwêzich is (bestelle binnen ien partition).

It is de muoite wurdich op te merken dat Kafka de folchoarder fan eveneminten mar binnen ien batch garandearret. Mar yn werklikheid is dit faaks gjin probleem. Jo kinne bygelyks der wis fan wêze dat jo alle wizigingen tafoegje oan deselde deklaraasje yn ien partition (sa behâlde de folchoarder fan dizze wizigingen binnen de ferklearring). Jo kinne ek stjoere in folchoarder nûmer yn ien fan de evenemint fjilden.

Konsumint

Kafka en mikrotsjinsten: in oersjoch

Konsumint is ferantwurdlik foar it heljen fan gegevens fan Apache Kafka. As wy weromgean nei it foarbyld hjirboppe, kin de konsumint in moderaasjetsjinst wêze. Dizze tsjinst sil ynskreaun wurde op it advertinsjetsjinst-ûnderwerp, en as in nije advertinsje ferskynt, sil it it ûntfange en analysearje foar neilibjen fan guon spesifisearre belied.

Apache Kafka ûnthâldt hokker resinte eveneminten de konsumint ûntfongen hat (dêrfoar wurdt in tsjinstûnderwerp brûkt __consumer__offsets), en soarget derfoar dat as it lêzen suksesfol is, de konsumint net twa kear itselde berjocht krijt. As jo ​​​​lykwols de opsje enable.auto.commit = wier brûke en it wurk fan it folgjen fan 'e posysje fan' e konsumint yn it ûnderwerp folslein delegearje oan Kafka, kinne jo ferlieze gegevens. Yn produksjekoade wurdt meastentiids de posysje fan 'e konsumint mei de hân kontrolearre (de ûntwikkelder kontroleart it momint dat de commit fan it lêzen barren moat foarkomme).

Yn gefallen dêr't ien konsumint is net genôch (bygelyks, de stream fan nije eveneminten is hiel grut), kinne jo tafoegje ferskate mear konsuminten troch te keppeljen se tegearre yn in konsumint groep. In konsumintegroep is logysk krekt itselde as in konsumint, mar mei gegevens ferdield ûnder groepsleden. Hjirmei kin elke dielnimmer har diel fan berjochten nimme, en dêrmei de lêssnelheid skaalje.

Testresultaten

Kafka en mikrotsjinsten: in oersjoch

Ik sil hjir net in protte ferklearjende tekst skriuwe, ik sil gewoan de resultaten diele. Testen waard útfierd op 3 fysike masines (12 CPU, 384GB RAM, 15k SAS DISK, 10GBit / s Net), makelders en zookeeper waarden ynset yn lxc.

Prestaasje testen

Tidens testen waarden de folgjende resultaten krigen.

  • De snelheid fan it tagelyk opnimmen fan 1KB-berjochten troch 9 produsinten is 1300000 eveneminten per sekonde.
  • De snelheid fan it lêzen fan 1KB-berjochten tagelyk troch 9 konsuminten is 1500000 eveneminten per sekonde.

Fault tolerance testen

Tidens it testen waarden de folgjende resultaten krigen (3 makelders, 3 zookeepers).

  • Abnormale beëiniging fan ien fan 'e brokers feroarsaket net dat it kluster stopet of net beskikber wurdt. It wurk giet gewoan troch, mar de oerbleaune makelders hawwe in swiere wurkdruk.
  • Abnormale beëiniging fan twa brokers yn it gefal fan in kluster fan trije brokers en min.isr = 2 liedt ta dat it kluster net beskikber is foar skriuwen, mar tagonklik foar lêzen. As min.isr = 1, bliuwt it kluster beskikber foar sawol lêzen as skriuwen. Dizze modus tsjinsprekt lykwols de eask foar hege gegevensfeiligens.
  • In abnormale ôfsluting fan ien fan 'e Zookeeper-tsjinners feroarsaket net dat it kluster stopet of net beskikber wurdt. It wurk giet gewoan troch.
  • In abnormale ôfsluting fan twa Zookeeper-tsjinners resultearret yn dat it kluster net beskikber is oant op syn minst ien fan 'e Zookeeper-tsjinners is weromset. Dizze útspraak is wier foar in Zookeeper-kluster fan 3 servers. As gefolch, nei ûndersyk, waard besletten om it Zookeeper-kluster te fergrutsjen nei 5 servers om fouttolerânsje te fergrutsjen.

Kafka as in tsjinst

Kafka en mikrotsjinsten: in oersjoch

Wy binne derfan oertsjûge dat Kafka in poerbêste technology is wêrmei wy de oan ús tawiisde taak oplosse kinne (it útfiere fan in berjochtmakelaar). Wy besletten lykwols om tsjinsten te ferbieden om direkt tagong te krijen ta Kafka en sluten it boppe-op mei in databustsjinst. Wêrom hawwe wy dit dien? Yn feite binne der nochal in pear redenen.

  • Data-bus naam alle taken oer yn ferbân mei yntegraasje mei Kafka (ymplemintaasje en konfiguraasje fan konsuminten en produsinten, tafersjoch, warskôging, logging, skaalfergrutting, ensfh.). Sa is yntegraasje mei de berjochtmakelaar sa ienfâldich mooglik.

  • Data-bus koe ús abstrahere fan in spesifike taal of bibleteek foar it wurkjen mei Kafka.

  • Data-bus liet oare tsjinsten de opslachlaach abstrahere. Miskien op in stuit sille wy feroarje Kafka nei Pulsar, en gjinien sil fernimme neat (alle tsjinsten allinne witte oer de data-bus API).

  • Data-bus naam de falidaasje fan eveneminteskema's oer.

  • Autentikaasje wurdt ymplementearre mei help fan data-bus.

  • Under de dekking fan databus kinne wy ​​Kafka-ferzjes rêstich bywurkje sûnder downtime, sintraal beheare konfiguraasjes fan produsinten, konsuminten, makelders, ensfh.

  • Data-bus liet ús de funksjes tafoegje dy't wy nedich wiene dy't net yn Kafka binne (lykas kontrolearjen fan ûnderwerpen, kontrolearjen fan anomalies yn it kluster, it meitsjen fan DLQ, ensfh.).

  • Data-bus lit jo failover sintraal ymplementearje foar alle tsjinsten.

Op it stuit, om te begjinnen mei it ferstjoeren fan eveneminten nei de berjochtmakelaar, moatte jo gewoan in lytse bibleteek ferbine mei jo tsjinstkoade. Dit is alles. Jo hawwe de mooglikheid om te skriuwen, lêzen en skaalfergrutting mei ien rigel koade. De heule ymplemintaasje is foar jo ferburgen, mei mar in pear hânfetten fan batchgrutte dy't útstekke. Under de kap bringt de databustsjinst it fereaske oantal produsint- en konsuminteksimplaren yn Kubernetes op en jout se de nedige konfiguraasje, mar dit alles is transparant foar jo tsjinst.

Fansels is d'r gjin sulveren kûgel, en dizze oanpak hat syn beheiningen.

  • Data-bus moat yn-hûs wurde stipe, yn tsjinstelling ta bibleteken fan tredden.
  • Data-bus fergruttet it oantal ynteraksjes tusken tsjinsten en de berjochtmakelaar, wat resulteart yn legere prestaasjes yn ferliking mei bleate Kafka.
  • Net alles kin sa maklik fan tsjinsten ferburgen wurde; wy wolle de funksjonaliteit fan KSQL of Kafka Streams net duplisearje yn databus, dus soms moatte wy tsjinsten tastean om direkt te gean.

Yn ús gefal wiene de foardielen de neidielen, en it beslút om de berjochtmakelaar te dekken mei in aparte tsjinst wie rjochtfeardige. Yn it wurkjier hawwe wy gjin serieuze ûngelokken of problemen hân.

PS Mei tank oan myn freondinne, Ekaterina Obalyaeva, foar de koele foto's foar dit artikel. As jo ​​se leuk fine, hjir der komme mear yllustraasjes.

Boarne: www.habr.com

Keapje betroubere hosting foar siden mei DDoS-beskerming, VPS VDS-tsjinners 🔥 Keapje betroubere websidehosting mei DDoS-beskerming, VPS VDS-tsjinners | ProHoster