Kafka ja mikroteenused: ülevaade

Kafka ja mikroteenused: ülevaade

Tere kõigile. Selles artiklis räägin, miks valisime Avitos Kafka üheksa kuud tagasi ja mida see endast kujutab. Jagame ühe kasutusjuhtumi – sõnumite vahendaja. Lõpetuseks arutame, milliseid eeliseid oleme saanud Kafka as a Service lähenemisviisi rakendamisest.

Probleem

Kafka ja mikroteenused: ülevaade

Alustuseks natuke konteksti. Mõni aeg tagasi hakkasime liikuma eemale monoliitsest arhitektuurist ning praegu on Avitos juba mitusada erinevat teenust. Neil on oma andmehoidlad, tehnoloogiapinnad ja nad vastutavad oma osa äriloogikast.

Üks probleem paljude teenustega on kommunikatsioon. Teenus A tahab sageli teada teavet, mida teenus B omab. Sellisel juhul pöördub teenus A teenuse B poole sünkroonse API kaudu. Teenus B tahab teada, mis toimub teenustes G ja D, samas kui need omakorda on huvitatud teenustest A ja B. Mida rohkem on selliseid „kurbuseid“ teenuseid, seda keerulisemaks muutuvad nendevahelised sidemed.

Selle juures võib teenus A igal hetkel saadamatuks jääda. Ja mida teha siis, kui teenus B ja kõik teised tema teenustele tuginevad teenused ei pruugi teenus A poole pöörduda? Kui äriprotsessi täitmiseks on vajalik teha ahel järjestikku sünkroonseid kutsungeid, suureneb kogu operatsiooni ebaõnnestumise tõenäosus veelgi (ja seda rohkem, mida pikem on see ahel).

Tehnoloogia valik

Kafka ja mikroteenused: ülevaade

Okei, probleemid on arusaadavad. Need saab lahendada, luues keskse sõnumite vahetuse süsteemi teenuste vahel. Nüüd peab igal teenusel olema lihtsalt teadmine sellest kontroll-süsteemist. Lisaks peab see süsteem olema veakindel ja horisontaalselt skaleeritav, samuti peab see katma helistamise ahelal esinevad hädad edasilugemiseks.

Valime nüüd tehnoloogia, millele sõnumite kohaletoimetamine põhineb. Esiteks mõistame, mida me sellelt ootame:

  • sõnumid teenuste vahel ei tohi kaduda;
  • sõnumid võivad olla duubeldatud;
  • sõnumid saab säilitada ja lugeda mitme päeva jooksul (püsiv vahemälu);
  • teenused võivad registreeruda huvipakkuvatele andmetele;
  • mitmed teenused võivad lugeda samu andmeid;
  • sõnumid võivad sisaldada detailset, mahukat koormust (event-carried state transfer);
  • mõnikord on vajalik sõnumite järjekorra garantii.

Meile oli kriitiliselt oluline valida võimalikult skaleeritav ja usaldusväärne süsteem, mille läbilaskevõime on vähemalt 100 000 sõnumit mõne kilobaidi sekundis.

Selles etapis ütlesime hüvasti RabbitMQ-le (raske hoida stabiilsena kõrgetes rps-des), SkyTools PGQ-le (ebapiisavalt kiire ja halvasti skaleeritav) ja NSQ-le (mitte püsiv). Kõiki neid tehnoloogiaid kasutatakse meie ettevõttes, kuid need ei sobinud antud ülesande jaoks.

Seejärel hakkasime vaatama uusi tehnoloogiaid — Apache Kafka, Apache Pulsar ja NATS Streaming.

Esimesena jätsime kõrvale Pulsari. Otsustasime, et Kafka ja Pulsar on omavahel üsna sarnased lahendused. Ja kuigi Pulsar on suurte ettevõtete poolt katsetatud, uuem ning teoreetiliselt pakub madalamat latentsust, otsustasime nende kahe hulgast jätta Kafka, kuna see on de facto standard selliste ülesannete jaoks. Tõenäoliselt pöördume Apache Pulsari juurde tulevikus tagasi.

Nii jäävad meil alles kaks kandidaati: NATS Streaming ja Apache Kafka. Uurisime mõlemaid lahendusi üsna põhjalikult, ja mõlemad sobisid meie ülesande jaoks. Kuid lõpuks pelgasime NATS Streaming'i suhtelist nooruslikkust (ja seda, et üks peamine arendaja, Tyler Treat, otsustas projektist lahkuda ja alustada oma — Liftbridge). Samuti ei pakkunud NATS Streaming'i klasterdamise režiim tugevat horisontaalset skaleerimist (tõenäoliselt ei ole see enam probleem pärast partitsioneerimisrežiimi lisamist 2017. aastal).

Sellegipoolest on NATS Streaming äge tehnoloogia, kirjutatud Go keeles ja toetatud Cloud Native Computing Foundation'i poolt. Erinevalt Apache Kafka'st ei vaja see tööks Zookeeperit (võimalik, et varsti võib sama öelda ka Kafka kohta), kuna seespool rakendab see RAFTi. Samal ajal on NATS Streaming lihtsam haldamiseks. Me ei välista, et tulevikus hakkame sellele tehnoloogiale tagasi pöörduma.

Kuid tänaseks on meie võitjaks saanud Apache Kafka. Meie testid näitasid, et see on piisavalt kiire (üle miljoni sõnumi sekundis lugemisel ja kirjutamisel mahus 1 kilobait), piisavalt usaldusväärne, hästi skaleeritav ja suurtelt ettevõtetelt testitud. Lisaks toetab Kafka vähemalt mitmeid suuri kommertsettevõtteid (me näiteks kasutame Confluent versiooni), samuti on Kafka'l arenenud ökosüsteem.

Kafka ülevaade

Enne alustamist soovitan kohe suurepärast raamatut — „Kafka: The Definitive Guide“ (on olemas ka vene tõlge, kuid terminid on veidi segased). Siit leiad teavet, mis on vajalik Kafka põhimõistmiseks ja isegi natuke rohkem. Apache’i dokumendid ja Confluenti blogi on samuti hästi kirjutatud ja kergesti loetavad.

Nii et vaatame, kuidas Kafka üles ehitatud on linnulennult. Kafka põhistruktuur koosneb producest, consumerist, brokerist ja zookeeperist.

Broker

Kafka ja mikroteenused: ülevaade

Teie andmete salvestamise eest vastutab broker (broker). Kõik andmed salvestatakse binaarses vormis, ja broker teab vähe sellest, mis nad endast kujutavad ja milline on nende struktuur.

Iga loogiline sündmuste tüüp asub tavaliselt eraldi teemas (topic). Näiteks, reklaami loomise sündmus võib minna teema item.created alla, samas kui selle muutmise sündmus läheb item.changed alla. Teemasid võib vaadelda sündmuste klassifikaatoritena. Teema tasandil saab seadistada selliseid konfiguratsiooni parameetreid nagu:

  • salvestatavate andmete maht ja/või nende vanus (retention.bytes, retention.ms);
  • andmete ülemäärasuse tegur (replication factor);
  • ühe sõnumi maksimaalne suurus (max.message.bytes);
  • minimaalne kooskõlastatud replikate arv, millega teema andmeid salvestada saab (min.insync.replicas);
  • võimalus viia läbi failide üleminek mitte-sünkroonse mahajääva replikaga, mille korral võib andmeid kaduda (unclean.leader.election.enable);
  • ja veel palju muud (https://kafka.apache.org/documentation/#topicconfigs).

Igal teema osal on omakorda üks või rohkem partitsioone (partition). Just partitsioonidesse satuvad sündmused. Kui klastris on rohkem kui üks broker, siis jaotatakse partitsioonid kõigi brokerite vahel ühtlaselt (kui see on võimalik), mis võimaldab koormust salvestamise ja lugemise osas üheaegselt mitme brokera vahel jagada.

Kettal salvestatakse iga partitsiooni andmed failide segmentidena, mis vaikimisi on ühe gigabaidi suurused (seda kontrollib log.segment.bytes). Oluline tähelepanek — partitsioonidest andmete eemaldamine (retention'i käivitamisel) toimub just segmentide kaupa (ei saa eemaldada ühte sündmust partitsioonist, vaid saab eemaldada vaid terve segment, ja see peab olema mitteaktiivne).

Zookeeper

Zookeeper täidab metadata ladustamise ja koordinaatori rolli. Just tema suudab öelda, kas brookerid on elus (vaadata seda zookeeperi silmade läbi saab zookeeper-shell käsuga ls /brokers/ids), milline broker on kontroller (get /controller), kas on osad sünkroneeritud olekuga oma koopiatega (get /brokers/topics/topic_name/partitions/partition_number/state). Samuti lähevad producent ja tarbija esmalt zookeeperisse, et teada saada, millisel vahendajal millised teemad ja osad on salvestatud. Kui teema jaoks on määratud replikatsiooni tegur suurem kui 1, näitab zookeeper, millised osad on juhid (neisse tehakse kirjutamine ja neist loetakse). Kui vahendaja kukub, salvestatakse zookeeperisse teave uute juhtivate osade kohta (alates versioonist 1.1.0 asünkroonselt, ja see on oluline).

Vanemates Kafka versioonides vastutas zookeeper ka offsetite salvestamise eest, kuid nüüd salvestatakse need spetsiaalsesse teemasse __consumer_offsets vahendajas (kuigi te saate endiselt kasutada zookeeperit nende eesmärkide jaoks).

Lihtsaim viis, kuidas oma andmed kõrvitsaks muuta, on just zookeeperi info kaotamine. Sel juhul on väga keeruline mõista, mida ja kust lugeda.

Producer

Producent on kõige sagedamini teenus, mis kirjutab andmeid otseselt Apache Kafka. Producent valib teema, kuhu tema temaatilised sõnumid salvestatakse, ja hakkab sinna teavet kirjutama. Näiteks võib producent olla kuulutuste teenus. Sellisel juhul saadab ta temaatilistesse teemadesse selliseid sündmusi nagu 'kuulutus loodud', 'kuulutus uuendatud', 'kuulutus kustutatud' jne. Iga sündmus esindab key-value paari.

Vaikimisi jaotatakse kõik sündmused teema osade vahel round-robin meetodil, kui võtme ei ole määratud (kaotades järjestuse), ja läbi MurmurHash (võti), kui võti on olemas (järjestus ühe osa raames).

Siinkohal tasub kohe märkida, et Kafka tagab sündmuste järjekorra ainult ühe osa raames. Kuid tegelikult ei ole see sageli probleem. Näiteks saab garanteeritult kõiki sama kuulutuse muudatusi lisada ühte osasse (pidades seeläbi muutuste järjekorda kuulutuse raames). Samuti võib edastada järjestusnumbri ühes sündmuse väljas.

Konsument

Kafka ja mikroteenused: ülevaade

Tarbijad vastutavad andmete saamise eest Apache Kafka's. Kui naasta eelneva näite juurde, võib consumer'iks olla modereerimisteenus. See teenus liitub kuulutuste teenuse teemaga ning kui ilmub uus kuulutus, saab see selle ja analüüsib vastavust teatud kehtestatud põhimõtetele.

Apache Kafka mäletab, milliseid viimaseid sündmusi consumer on saanud (selleks kasutatakse teenuse teemat __consumer__offsets), tagades, et kui read on edukad, ei saa consumer kunagi sama sõnumit kaks korda. Siiski, kui kasutada valikut enable.auto.commit = true ja usaldada consumer'i asukoha jälgimine täielikult Kafka kätte, võib andmeid kaotada. Tootmisooditud koodis jälgib consumer'i positsiooni enamasti käsitsi (arendaja haldab hetke, millal peab toimuma loetud sündmuse commit).

Juhtudel, kui üks consumer ei piisa (näiteks kui uusi sündmusi on väga palju), saab lisada veel mõned consumer'id, seostades need omavahel consumer gruppi. Consumer grupp esindab loogiliselt sama consumer'it, kuid andmed jaotatakse gruppi kuuluvate osalejate vahel. See võimaldab igaühel osalejatest võtta oma osa sõnumitest, suurendades seeläbi lugemise kiirus.

Testimise tulemused

Kafka ja mikroteenused: ülevaade

Siin ei hakka ma kirjutama palju selgitavaid tekste, lihtsalt jagan saadud tulemusi. Katsetamine toimus 3 füüsilisel masinal (12 CPU, 384GB RAM, 15k SAS DISK, 10GBit/s Net), brokerid ja zookeeper olid paigaldatud lxc.

Tootlikkuse testimine

Katsetamise käigus saadi järgmised tulemused.

  • 1KB suuruste sõnumite kirjutamise kiirus 9 producer'iga on - 1300000 sündmust sekundis.
  • 1KB suuruste sõnumite lugemise kiirus 9 consumer'iga on - 1500000 sündmust sekundis.

Vigasetootlikkuse katsetamine

Katsetamise käigus saadi järgmised tulemused (3 brokerit, 3 zookeeper'it).

  • Ühe brokeri mittetöötamine ei põhjusta klastrite seiskumist või kättesaamatust. Töö jätkub tavapäraselt, kuid ülejäänud brokeritele langeb suurem koormus.
  • Kaks Zookeeperi brokera ootamatut sulgemist kolmekesi klastris, kus min.isr = 2, toob kaasa klastrite kättesaamatuse kirjutamiseks, kuid lugemiseks jääb see kättesaadavaks. Kui min.isr = 1, püsib klaster kättesaadavana nii lugemiseks kui ka kirjutamiseks. Siiski on see režiim vastuolus andmete kõrge säilitamise nõudega.
  • Ühe Zookeeperi serveri ootamatu sulgemine ei lõpeta ega tee klastrit kättesaamatuks. Töö jätkub tavarežiimis.
  • Kaks Zookeeperi serveri ootamatut sulgemist toob kaasa klastrite kättesaamatuse kuni vähemalt ühe Zookeeperi serveri töö taastamiseni. See väide kehtib ka Zookeeperi kolme serveri klastrite kohta. Seetõttu otsustati suurendada Zookeeperi klastrit viiele serverile, et suurendada talitlushäiret põhjustavat vastupidavust.

Kafka teenusena

Kafka ja mikroteenused: ülevaade

Oleme veendunud, et Kafka on suurepärane tehnoloogia, mis lahendab meie väljakuulutatud ülesande (sõnumi vahendaja rakendamine). Sellegipoolest otsustasime keelata teenustel otse Kafka juurde pääsu ja sulgesime selle data-bus teenuse kaudu. Miks me seda tegime? Tegelikult on mitu põhjust.

  • Data-bus on endale võtnud kõik Kafka integreerimisega seotud ülesanded (consumerite ja producerite rakendamine ja seadistamine, järelevalve, häired, logimine, skaleerimine jne). Seega toimub integreerimine sõnumite brokera juurde maksimaalselt lihtsalt.

  • Data-bus võimaldas abstracteerida konkreetse keele või teegi Kafka kasutamiseks.

  • Data-bus võimaldas teistel teenustel abstracteerida salvestuskihti. Võib-olla vahetame kunagi Kafka Pulsari vastu, ja keegi ei märka isegi (kõik teenused tunnevad ainult data-bus API-t).

  • Data-bus on vastutanud sündmuste skeemide valideerimise eest.

  • Data-bus kaudu on rakendatud autentimine.

  • Data-bus'i kaudu saame ilma seisakuta ja märkamatult Kafka versioone uuendada, hallata keskelt producerite, consumerite, brokerite konfiguratsioone jne.

  • Data-bus on võimaldanud lisada vajalikke funktsioone, mida Kafka-l ei ole (nt teema auditeerimine, klastris esinevate anomaaliate kontrollimine, DLQ loomine jne).

  • Data-bus võimaldab rakendada failoveri kõigile teenustele keskelt.

Praegu on sõnumite saatmise alustamiseks piisav, kui ühendate oma teenuse koodis väikese teegi. See on kõik. Teil on võimalus kirjutada, lugeda ja skaleerida ühe koodirea abil. Kogu teostus on teie eest varjatud, nähtavale jääb vaid paar käepidet, nagu partii suurus. Sügaval teenuse data-bus all tõstab Kubernetes vajalikud producer’ite ja consumer’ite instantsid ja seab neile vajalikud konfiguratsioonid, kuid see kõik on teie teenusele läbipaistmatu.

Loomulikult ei ole hõbedast kuulit, ja sellisel lähenemisel on omad piirangud.

  • Data-bus tuleb ise toetada, erinevalt kolmandate osapoolte teekidest.
  • Data-bus suurendab teenuste ja sõnumite vahendaja vahelisi interaktsioone, mis toob kaasa jõudluse languse võrreldes puhta Kafka-ga.
  • Kaugel pole kõike nii lihtsalt teenustelt varjata, me ei soovi dubleerida KSQL või Kafka Streams funktsionaalsust data-bus'is, seega tuleb mõnikord lubada teenustel ühenduda otse.

Meie puhul ületasid plussid miinuseid ning otsus peita sõnumite vahendaja eraldiseisva teenusena osutus õigeks. Ühe aasta jooksul ei ole meil olnud olulisi avariisid ega probleeme.

P.S. Aitäh minu tüdruksõbrale, Ekaterina Obalyaevale, selle artikli ägedate piltide eest. Kui need teile meeldisid, siit leidub veel rohkem illustratsioone.

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster