Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Čo by mohlo prinútiť takú veľkú spoločnosť, akou je Lamoda, so zefektívneným procesom a desiatkami vzájomne prepojených služieb výrazne zmeniť svoj prístup? Motivácia môže byť úplne iná: od legislatívnej až po túžbu experimentovať, ktorá je vlastná všetkým programátorom.

To však neznamená, že nemôžete počítať s ďalšími výhodami. Sergey Zaika vám povie, čo presne môžete vyhrať, ak implementujete API riadené udalosťami na Kafka (fewald). Určite bude reč aj o veľkých záberoch a zaujímavých objavoch – bez nich sa experiment nezaobíde.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Vyhlásenie: Tento článok je založený na materiáloch zo stretnutia, ktoré Sergey usporiadal v novembri 2018 na HighLoad++. Lamodova živá skúsenosť zo spolupráce s Kafkom prilákala poslucháčov o nič menej ako iné správy v programe. Myslíme si, že toto je vynikajúci príklad toho, že vždy môžete a mali by ste nájsť rovnako zmýšľajúcich ľudí a organizátori HighLoad++ sa budú aj naďalej snažiť vytvárať atmosféru, ktorá k tomu prispieva.

O procese

Lamoda je veľká e-commerce platforma, ktorá má vlastné kontaktné centrum, donáškovú službu (a mnoho pobočiek), fotoštúdio, obrovský sklad a to všetko beží na vlastnom softvéri. Existujú desiatky platobných metód, b2b partnerov, ktorí môžu využívať niektoré alebo všetky tieto služby a chcú poznať aktuálne informácie o svojich produktoch. Lamoda navyše pôsobí okrem Ruskej federácie v troch krajinách a tam je všetko trochu inak. Celkovo existuje pravdepodobne viac ako sto spôsobov, ako nakonfigurovať novú objednávku, ktorá musí byť spracovaná vlastným spôsobom. To všetko funguje s pomocou desiatok služieb, ktoré niekedy komunikujú nezrozumiteľnými spôsobmi. Existuje aj centrálny systém, ktorého hlavnou zodpovednosťou sú stavy objednávok. Voláme ju BOB, spolupracujem s ňou.

Nástroj na vrátenie platby s rozhraním API riadeným udalosťami

Slovo riadené udalosťami je dosť otrepané, o niečo ďalej podrobnejšie definujeme, čo sa tým myslí. Začnem kontextom, v ktorom sme sa rozhodli vyskúšať prístup API riadený udalosťami v Kafke.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

V každom obchode sa okrem objednávok, za ktoré platia zákazníci, vyskytnú prípady, keď je obchod povinný vrátiť peniaze, pretože produkt zákazníkovi nevyhovoval. Ide o pomerne krátky proces: v prípade potreby objasníme informácie a prevedieme peniaze.

No návrat sa pre zmeny legislatívy skomplikoval a museli sme naň implementovať samostatnú mikroslužbu.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Naša motivácia:

  1. Zákon FZ-54 - v skratke, zákon vyžaduje nahlásiť daňovému úradu každú peňažnú transakciu, či už ide o vratku alebo potvrdenie, v pomerne krátkej SLA v priebehu niekoľkých minút. My ako e-commerce spoločnosť realizujeme pomerne veľa operácií. Technicky to znamená novú zodpovednosť (a teda aj novú službu) a vylepšenia všetkých zapojených systémov.
  2. BOB rozdelenie je interný projekt spoločnosti na odbremenenie BOB od veľkého množstva vedľajších povinností a zníženie jeho celkovej zložitosti.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Tento diagram ukazuje hlavné systémy Lamoda. Teraz ich je viac konštelácia 5-10 mikroslužieb okolo zmenšujúceho sa monolitu. Pomaly rastú, no snažíme sa ich zmenšiť, pretože nasadenie úlomku vybratého v strede je desivé – nesmieme dovoliť, aby spadol. Všetky výmeny (šípky) sme nútení rezervovať a počítať s tým, že ktorákoľvek z nich sa môže ukázať ako nedostupná.

BOB má tiež pomerne veľa búrz: platobné systémy, doručovacie systémy, oznamovacie systémy atď.

Technicky BOB je:

  • ~150 100 riadkov kódu + ~ XNUMX XNUMX riadkov testov;
  • php7.2 + Zend 1 a Symfony Components 3;
  • > 100 rozhraní API & ~ 50 odchádzajúcich integrácií;
  • 4 krajiny s vlastnou obchodnou logikou.

Nasadenie BOB je drahé a bolestivé, množstvo kódu a problémov, ktoré rieši, je také, že si to nikto všetko nevloží do hlavy. Vo všeobecnosti existuje veľa dôvodov na jeho zjednodušenie.

Proces vrátenia

Spočiatku sú do procesu zapojené dva systémy: BOB a platba. Teraz sa objavia ďalšie dve:

  • Fiskalizačná služba, ktorá sa postará o problémy s fiskalizáciou a komunikáciou s externými službami.
  • Refund Tool, ktorý jednoducho obsahuje nové výmeny, aby nenafúkol BOB.

Teraz proces vyzerá takto:

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

  1. BOB dostane žiadosť o vrátenie peňazí.
  2. BOB hovorí o tomto nástroji na vrátenie platby.
  3. Nástroj na vrátenie platby hovorí Platbe: „Vráťte peniaze“.
  4. Platba vráti peniaze.
  5. Nástroj Refund Tool a BOB navzájom synchronizujú stavy, pretože zatiaľ to obaja potrebujú. Ešte nie sme pripravení úplne prejsť na Nástroj na vrátenie peňazí, keďže BOB má používateľské rozhranie, výkazy pre účtovníctvo a vo všeobecnosti množstvo údajov, ktoré sa nedajú tak ľahko preniesť. Musíte sedieť na dvoch stoličkách.
  6. Žiadosť o fiškáláciu zmizne.

Výsledkom bolo, že sme na Kafke urobili akýsi eventový autobus – event-bus, na ktorom sa všetko začalo. Hurá, teraz máme jediný bod zlyhania (sarkazmus).

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Výhody a nevýhody sú celkom zrejmé. Urobili sme autobus, čo znamená, že teraz sú od neho závislé všetky služby. To zjednodušuje dizajn, ale vnáša do systému jediný bod zlyhania. Kafka sa zrúti, proces sa zastaví.

Čo je API riadené udalosťami

Dobrá odpoveď na túto otázku je v reportáži Martina Fowlera (GOTO 2017) „Mnohé významy architektúry riadenej udalosťami“.

Čo sme urobili v skratke:

  1. Zbaliť všetky asynchrónne výmeny cez ukladanie udalostí. Namiesto toho, aby sme každého zainteresovaného spotrebiteľa informovali o zmene stavu cez sieť, napíšeme udalosť o zmene stavu na centralizované úložisko a spotrebitelia, ktorí sa zaujímajú o túto tému, čítajú všetko, čo sa odtiaľ objaví.
  2. Udalosťou je v tomto prípade oznámenie (oznámenia), že sa niekde niečo zmenilo. Zmenil sa napríklad stav objednávky. Spotrebiteľ, ktorý má záujem o niektoré údaje sprevádzajúce zmenu stavu, ktoré nie sú zahrnuté v oznámení, si ich stav môže zistiť sám.
  3. Maximálnou možnosťou je plnohodnotný zdroj udalostí, štátny prevod, ktorá udalosť obsahuje všetky informácie potrebné na spracovanie: odkiaľ pochádza a do akého stavu sa dostala, ako presne sa údaje zmenili atď. Jedinou otázkou je uskutočniteľnosť a množstvo informácií, ktoré si môžete dovoliť uložiť.

V rámci spustenia Nástroja na vrátenie peňazí sme využili tretiu možnosť. Toto zjednodušilo spracovanie udalostí, pretože nebolo potrebné extrahovať podrobné informácie, a navyše to eliminovalo scenár, v ktorom každá nová udalosť generuje množstvo objasňujúcich požiadaviek od spotrebiteľov.

Služba nástroja na vrátenie peňazí nenačítané, takže Kafka je tu skôr chuť pera ako nutnosť. Nemyslím si, že keby sa služba vrátenia peňazí stala projektom s vysokým zaťažením, podnikanie by bolo šťastné.

Asynchrónna výmena AKO JE

Pre asynchrónne výmeny používa oddelenie PHP zvyčajne RabbitMQ. Zozbierali sme údaje pre požiadavku, zaradili sme ju do poradia a spotrebiteľ tej istej služby si ich prečítal a odoslal (alebo neodoslal). Pre samotné API Lamoda aktívne používa Swagger. Navrhneme API, popíšeme ho v Swagger a vygenerujeme klientsky a serverový kód. Používame tiež mierne vylepšený JSON RPC 2.0.

Na niektorých miestach sa používajú autobusy ESB, niektoré žijú na activeMQ, ale vo všeobecnosti RabbitMQ - štandard.

Asynchrónna výmena TO BE

Pri navrhovaní výmeny cez zbernicu udalostí možno vysledovať analógiu. Podobne popisujeme budúcu výmenu dát prostredníctvom popisov štruktúry udalostí. Formát yaml, generovanie kódu sme si museli urobiť sami, generátor vytvára DTO podľa špecifikácie a učí klientov a servery s nimi pracovať. Generácia ide do dvoch jazykov - golang a php. Pomáha to udržiavať konzistentnosť knižníc. Generátor je napísaný v golangu, preto dostal názov gogi.

Event-sourcing na Kafku je typická vec. Existuje riešenie z hlavnej podnikovej verzie Kafka Confluent, existuje nakadi, riešenie od našich doménových bratov Zalando. náš motivácia začať s vanilkovým Kafkom - to znamená nechať riešenie voľnú ruku, kým sa definitívne nerozhodneme, či ho budeme používať všade, a tiež si ponechať priestor na manévrovanie a vylepšenia: chceme podporu pre naše JSON RPC 2.0, generátory pre dva jazyky a uvidíme, čo ešte.

Je iróniou, že ani v takomto šťastnom prípade, keď existuje zhruba podobný biznis, Zalando, ktorý urobil zhruba podobné riešenie, ho nevieme efektívne využiť.

Architektonický vzor pri spustení je nasledovný: čítame priamo od Kafku, ale píšeme len cez event-bus. V Kafkovi je toho veľa na čítanie: makléri, balancery a je to viac-menej pripravené na horizontálne škálovanie, toto som chcel ponechať. Chceli sme dokončiť nahrávanie cez jeden Gateway aka Events-bus, a tu je dôvod.

Podujatia-autobus

Alebo eventový autobus. Toto je jednoducho bezstavová http brána, ktorá preberá niekoľko dôležitých úloh:

  • Produkcia validácie — kontrolujeme, či udalosti spĺňajú naše špecifikácie.
  • Master systém udalostí, to znamená, že toto je hlavný a jediný systém v spoločnosti, ktorý odpovedá na otázku, ktoré udalosti s akými štruktúrami sa považujú za platné. Validácia jednoducho zahŕňa dátové typy a zoznamy, ktoré presne špecifikujú obsah.
  • Hash funkcia pre sharding - štruktúra správy Kafka je kľúč-hodnota a pomocou hash kľúča sa vypočíta, kam ju umiestniť.

Prečo

Pracujeme vo veľkej spoločnosti s efektívnym procesom. Prečo niečo meniť? Toto je experimenta očakávame, že získame niekoľko výhod.

Výmeny 1:n+1 (jedna k mnohým)

Kafka veľmi uľahčuje pripojenie nových spotrebiteľov k API.

Povedzme, že máte adresár, ktorý potrebujete aktualizovať v niekoľkých systémoch naraz (a v niektorých nových). Predtým sme vynašli balík, ktorý implementoval set-API a hlavný systém bol informovaný o adresách spotrebiteľov. Teraz hlavný systém posiela aktualizácie k téme a každý, kto má záujem, si to prečíta. Objavil sa nový systém – prihlásili sme ho do témy. Áno, tiež zväzok, ale jednoduchšie.

V prípade nástroja na vrátenie peňazí, ktorý je súčasťou BOB, je pre nás vhodné udržiavať ich synchronizované prostredníctvom Kafky. Platba hovorí, že peniaze boli vrátené: BOB, RT sa o tom dozvedeli, zmenili svoj stav, Fiskalizačná služba sa o tom dozvedela a vystavila šek.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Máme v pláne vytvoriť jednotnú Notifikačnú službu, ktorá by klienta informovala o novinkách ohľadom jeho objednávky/vrátenia tovaru. Teraz je táto zodpovednosť rozdelená medzi systémy. Bude nám stačiť naučiť Službu upozornení zachytiť relevantné informácie od Kafku a reagovať na ne (a deaktivovať tieto upozornenia v iných systémoch). Nebudú potrebné žiadne nové priame výmeny.

Na základe údajov

Informácie medzi systémami sa stanú transparentnými – bez ohľadu na to, aký „krvavý podnik“ máte, a bez ohľadu na to, aké veľké sú vaše nevybavené veci. Lamoda má oddelenie Data Analytics, ktoré zhromažďuje údaje zo systémov a dáva ich do opätovne použiteľnej formy pre podnikanie aj pre inteligentné systémy. Kafka vám umožňuje rýchlo im poskytnúť množstvo údajov a udržiavať tento tok informácií aktuálny.

Protokol replikácie

Správy po prečítaní nezmiznú, ako v RabbitMQ. Keď udalosť obsahuje dostatok informácií na spracovanie, máme históriu nedávnych zmien objektu a v prípade potreby možnosť tieto zmeny použiť.

Doba uloženia protokolu replikácie závisí od intenzity zápisu do tejto témy, Kafka umožňuje flexibilne nastaviť limity na čas uloženia a objem dát. Pri intenzívnych témach je dôležité, aby si všetci spotrebitelia stihli prečítať informácie skôr, ako zmiznú, a to aj v prípade krátkodobej nefunkčnosti. Zvyčajne je možné ukladať údaje pre jednotky dní, čo je na podporu celkom dosť.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Ďalej malé prerozprávanie dokumentácie, pre tých, ktorí nepoznajú Kafku (obrázok je tiež z dokumentácie)

AMQP má fronty: píšeme správy do frontu pre spotrebiteľa. Typicky je jeden front spracovaný jedným systémom s rovnakou obchodnou logikou. Ak potrebujete upozorniť viacero systémov, môžete aplikáciu naučiť zapisovať do viacerých frontov alebo nakonfigurovať výmenu pomocou mechanizmu fanout, ktorý ich sám naklonuje.

Podobnú abstrakciu má aj Kafka aktuálne, do ktorej píšete správy, ktoré však po prečítaní nezmiznú. V predvolenom nastavení, keď sa pripojíte ku Kafke, dostanete všetky správy a máte možnosť uložiť tam, kde ste prestali. To znamená, že čítate postupne, správu nesmiete označiť ako prečítanú, ale uložíte si ID, z ktorého potom môžete pokračovať v čítaní. Id, na ktorom ste sa usadili, sa nazýva offset a mechanizmus je posun potvrdenia.

V súlade s tým môže byť implementovaná iná logika. Napríklad máme BOB v 4 prípadoch pre rôzne krajiny - Lamoda je v Rusku, Kazachstane, Ukrajine, Bielorusku. Keďže sú nasadené samostatne, majú mierne odlišné konfigurácie a vlastnú obchodnú logiku. V správe uvádzame, ktorej krajiny sa týka. Každý spotrebiteľ BOB v každej krajine číta s iným groupId a ak sa ich správa netýka, preskočia ju, t.j. okamžite vykoná offset +1. Ak tú istú tému číta naša Platobná služba, robí to so samostatnou skupinou, a preto sa offsety nepretínajú.

Požiadavky na podujatie:

  • Úplnosť údajov. Bol by som rád, keby udalosť mala dostatok údajov na jej spracovanie.

  • Integrity. Na Events-bus delegujeme overenie, že udalosť je konzistentná a dokáže ju spracovať.
  • Poradie je dôležité. V prípade návratu sme nútení pracovať s históriou. Pri notifikáciách nie je dôležitá objednávka, ak ide o homogénne notifikácie, email bude rovnaký bez ohľadu na to, ktorá objednávka prišla ako prvá. V prípade vrátenia peňazí je proces jasný, ak zmeníme objednávku, vzniknú výnimky, refundácia sa nevytvorí ani nespracuje - skončíme v inom stave.
  • Dôslednosť. Máme obchod a teraz namiesto API vytvárame udalosti. Potrebujeme spôsob, ako rýchlo a lacno prenášať informácie o nových udalostiach a zmenách existujúcich do našich služieb. To sa dosiahne prostredníctvom spoločnej špecifikácie v samostatnom úložisku git a generátoroch kódu. Preto sú klienti a servery v rôznych službách koordinované.

Kafka v Lamode

Máme tri Kafkove inštalácie:

  1. Záznamy;
  2. výskum a vývoj;
  3. Podujatia-autobus.

Dnes hovoríme len o poslednom bode. Na event-bus nemáme veľmi veľké inštalácie - 3 brokeri (servery) a len 27 tém. Jedna téma je spravidla jeden proces. Ale toto je jemný bod a my sa ho teraz dotkneme.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Hore je graf otáčok. Proces vrátenia peňazí je označený tyrkysovou čiarou (áno, tá na osi X) a ružová čiara je proces aktualizácie obsahu.

Katalóg Lamoda obsahuje milióny produktov a údaje sa neustále aktualizujú. Niektoré kolekcie vychádzajú z módy, vydávajú sa nové, ktoré ich nahradia a v katalógu sa neustále objavujú nové modely. Snažíme sa predpovedať, čo bude pre našich zákazníkov zajtra zaujímavé, preto neustále nakupujeme nové veci, fotíme ich a aktualizujeme vitrínu.

Ružové vrcholy sú aktualizácie produktov, teda zmeny produktov. Je vidieť, že chalani fotili, fotili a potom ešte raz! — naložil balík udalostí.

Prípady použitia Lamoda Events

Skonštruovanú architektúru používame na nasledujúce operácie:

  • Sledovanie stavu vrátenia: výzva na akciu a sledovanie stavu zo všetkých zapojených systémov. Platba, stavy, fiskalizácia, notifikácie. Tu sme testovali prístup, vyrobili nástroje, pozbierali všetky chyby, napísali dokumentáciu a povedali našim kolegom, ako ho používať.
  • Aktualizácia produktových kariet: konfigurácia, metaúdaje, charakteristiky. Jeden systém číta (ktorý zobrazuje) a niekoľko zapisuje.
  • Email, push a sms: objednávka bola vyzdvihnutá, objednávka dorazila, vrátenie bolo prijaté atď., je ich veľa.
  • Sklad, obnova skladu — kvantitatívna aktualizácia položiek, len čísla: príchod na sklad, vrátenie. Je potrebné, aby všetky systémy spojené s rezerváciou tovaru fungovali s najaktuálnejšími údajmi. V súčasnosti je systém aktualizácie akcií pomerne zložitý, Kafka ho zjednoduší.
  • Analýza dát (oddelenie výskumu a vývoja), nástroje ML, analytika, štatistika. Chceme, aby informácie boli transparentné – Kafka je na to vhodný.

Teraz tá zaujímavejšia časť o veľkých prevratoch a zaujímavých objavoch, ktoré sa udiali za posledných šesť mesiacov.

Problémy s dizajnom

Povedzme, že chceme urobiť novú vec – napríklad preniesť celý proces doručenia na Kafku. Teraz je časť procesu implementovaná v Spracovaní objednávok v BOB. Za odovzdaním zákazky doručovacej službe, presunom na medzisklad a pod. je stavový model. Existuje celý monolit, dokonca dva, plus množstvo rozhraní API určených na doručovanie. O doručení vedia oveľa viac.

Zdá sa, že ide o podobné oblasti, ale Spracovanie objednávok v BOB a Expedičný systém majú odlišné stavy. Napríklad niektoré kuriérske služby neposielajú medzistavy, ale iba konečné: „doručené“ alebo „stratené“. Iní, naopak, veľmi podrobne informujú o pohybe tovaru. Každý má svoje vlastné pravidlá overovania: pre niektorých je e-mail platný, čo znamená, že bude spracovaný; pre ostatných to neplatí, ale objednávka sa aj tak vybaví, lebo je tam telefónne číslo na kontakt, a niekto povie, že takáto objednávka nebude vybavená vôbec.

Dátový tok

V prípade Kafku vyvstáva otázka organizácie toku dát. Táto úloha zahŕňa výber stratégie založenej na niekoľkých bodoch; poďme si ich všetky prejsť.

V jednej téme alebo v rôznych?

Máme špecifikáciu udalosti. V BOB napíšeme, že je potrebné dodať takú a takú objednávku a uviesť: číslo objednávky, jej zloženie, niektoré SKU a čiarové kódy atď. Keď tovar dorazí na sklad, dodávka bude môcť prijímať stavy, časové pečiatky a všetko, čo je potrebné. Potom však chceme dostávať aktualizácie týchto údajov v BOB. Máme opačný proces prijímania údajov od doručenia. Je to tá istá udalosť? Alebo ide o samostatnú burzu, ktorá si zaslúži vlastnú tému?

S najväčšou pravdepodobnosťou budú veľmi podobné a pokušenie vytvoriť jednu tému nie je neopodstatnené, pretože samostatná téma znamená samostatných spotrebiteľov, samostatné konfigurácie, samostatnú generáciu toho všetkého. Ale nie fakt.

Nové ihrisko alebo nové podujatie?

Ale ak použijete rovnaké udalosti, potom nastáva ďalší problém. Napríklad nie všetky doručovacie systémy dokážu generovať druh DTO, ktorý dokáže generovať BOB. Pošleme im ID, ale neuložia si ho, pretože ho nepotrebujú a z hľadiska spustenia procesu zbernice udalostí je toto pole povinné.

Ak zavedieme pravidlo pre zbernicu udalostí, že toto pole je povinné, potom sme nútení nastaviť ďalšie overovacie pravidlá v BOB alebo v obsluhe udalosti spustenia. Validácia sa začína šíriť po celej službe - to nie je príliš pohodlné.

Ďalším problémom je pokušenie postupného rozvoja. Hovorí sa nám, že k udalosti treba niečo dodať a možno, keď sa nad tým zamyslíme, mala to byť samostatná akcia. Ale v našej schéme je samostatná udalosť samostatnou témou. Samostatnou témou je celý proces, ktorý som opísal vyššie. Vývojár je v pokušení jednoducho pridať ďalšie pole do schémy JSON a vygenerovať ho.

V prípade vrátenia peňazí sme na akciu akcie dorazili až o pol roka. Mali sme jednu metaudalosť s názvom aktualizácia vrátenia peňazí, ktorá mala pole typu popisujúce, čo táto aktualizácia vlastne bola. Z tohto dôvodu sme mali „úžasné“ prepínače s validátormi, ktorí nám povedali, ako overiť túto udalosť s týmto typom.

Verzia udalostí

Na overenie správ v Kafke môžete použiť Avro, no bolo potrebné si naň okamžite ľahnúť a použiť Confluent. V našom prípade musíme byť opatrní pri vytváraní verzií. Nie vždy bude možné znovu prečítať správy z replikačného protokolu, pretože model „odišiel“. V zásade sa ukazuje, že sa zostavujú verzie tak, aby bol model spätne kompatibilný: napríklad, aby pole bolo dočasne voliteľné. Ak sú rozdiely príliš veľké, začneme písať novú tému a klientov presunieme, keď dočítajú starú.

Zaručené poradie čítania oddielov

Témy vo vnútri Kafky sú rozdelené do oddielov. Toto nie je veľmi dôležité, keď navrhujeme entity a burzy, ale je to dôležité pri rozhodovaní o tom, ako to spotrebovať a škálovať.

V bežnom prípade napíšete jednu tému v Kafkovi. Štandardne sa používa jeden oddiel a všetky správy v tejto téme idú naň. A spotrebiteľ následne číta tieto správy postupne. Povedzme, že teraz potrebujeme rozšíriť systém tak, aby správy čítali dvaja rôzni spotrebitelia. Ak napríklad posielate SMS, môžete Kafkovi povedať, aby vytvoril ďalší oddiel, a Kafka začne deliť správy na dve časti – polovicu tu, polovicu tu.

Ako ich Kafka delí? Každá správa má telo (v ktorom ukladáme JSON) a kľúč. K tomuto kľúču môžete pripojiť hašovaciu funkciu, ktorá určí, do ktorého oddielu sa správa dostane.

V našom prípade s refundáciami je to dôležité, ak vezmeme dva oddiely, potom je šanca, že paralelný spotrebiteľ spracuje druhú udalosť pred prvou a bude problém. Hašovacia funkcia zabezpečuje, že správy s rovnakým kľúčom skončia v rovnakom oddiele.

Udalosti vs príkazy

Toto je ďalší problém, s ktorým sme sa stretli. Udalosť je určitá udalosť: hovoríme, že sa niekde niečo stalo (niečo_ sa stalo), napríklad bola zrušená položka alebo došlo k vráteniu peňazí. Ak si niekto vypočuje tieto udalosti, potom podľa „položka zrušená“ sa vytvorí entita vrátenia platby a niekde v nastaveniach sa napíše „vrátenie platby“.

Ale zvyčajne, keď navrhujete udalosti, nechcete ich písať zbytočne - spoliehate sa na to, že ich niekto bude čítať. Existuje veľké pokušenie napísať nie niečo_ sa stalo (item_canceled, refund_refunded), ale something_should_be_done. Napríklad položka je pripravená na vrátenie.

Na jednej strane naznačuje, ako sa podujatie využije. Na druhej strane to znie oveľa menej ako bežný názov udalosti. Okrem toho to odtiaľto nie je ďaleko k príkazu urobiť_niečo. Ale nemáte žiadnu záruku, že niekto čítal túto udalosť; a ak si to prečítate, potom to prečítate úspešne; a ak si to úspešne prečítal, tak si niečo urobil, a to sa niečo podarilo. V momente, keď sa z udalosti stane niečo urobiť, je potrebná spätná väzba, a to je problém.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

V asynchrónnej výmene v RabbitMQ, keď si prečítate správu, prejdite na http, máte odpoveď - aspoň, že správa bola prijatá. Keď píšete Kafkovi, je tam správa, že ste písali Kafkovi, ale neviete nič o tom, ako bola spracovaná.

Preto sme v našom prípade museli zaviesť odozvovú udalosť a nastaviť monitoring tak, aby ak bolo odoslaných toľko udalostí, po takom a takom čase mal prísť rovnaký počet odozvových udalostí. Ak sa tak nestane, potom sa zdá, že sa niečo pokazilo. Ak sme napríklad odoslali udalosť „item_ready_to_refund“, očakávame, že sa vytvorí refundácia, peniaze sa vrátia klientovi a odošle sa nám udalosť „money_refunded“. To však nie je isté, preto je potrebný monitoring.

nuansy

Je tu celkom zrejmý problém: ak čítate z témy postupne a máte nejaké zlé správy, spotrebiteľ padne a ďalej nepôjdete. Potrebuješ zastaviť všetkých spotrebiteľov, potvrďte posun ďalej, aby ste mohli pokračovať v čítaní.

Vedeli sme o tom, počítali sme s tým, a predsa sa to stalo. A to sa stalo preto, lebo udalosť bola platná z pohľadu event-bus, udalosť platila z pohľadu validátora aplikácie, ale nebola platná z pohľadu PostgreSQL, pretože v našom systéme MySQL s UNSIGNED INT systém mal PostgreSQL práve s INT. Jeho veľkosť je trochu menšia a ID sa nezmestilo. Symfony zomrel s výnimkou. Výnimku sme, samozrejme, zachytili, pretože sme sa na ňu spoliehali a chystali sme sa vykonať tento offset, ale predtým sme chceli zvýšiť počítadlo problémov, keďže správa bola spracovaná neúspešne. Počítadlá v tomto projekte sú tiež v databáze a Symfony už ukončilo komunikáciu s databázou a druhá výnimka zabila celý proces bez šance na spáchanie offsetu.

Služba na nejaký čas ustála - našťastie s Kafkom to nie je také zlé, pretože správy zostávajú. Po obnovení práce ich môžete dokončiť. Je to pohodlné.

Kafka má schopnosť nastaviť ľubovoľný posun pomocou nástrojov. Aby ste to však urobili, musíte zastaviť všetkých spotrebiteľov - v našom prípade pripravte samostatné vydanie, v ktorom nebudú žiadni spotrebitelia, presuny. Potom v Kafke môžete posunúť posun pomocou nástrojov a správa prejde.

Ďalšia nuansa - replikačný protokol vs rdkafka.so - súvisí so špecifikami nášho projektu. Používame PHP a v PHP spravidla všetky knižnice komunikujú s Kafkom cez úložisko rdkafka.so a potom je tu nejaký obal. Možno sú to naše osobné ťažkosti, ale ukázalo sa, že jednoducho znovu prečítať kúsok z toho, čo sme už prečítali, nie je také jednoduché. Vo všeobecnosti sa vyskytli problémy so softvérom.

Ak sa vrátime k špecifikám práce s oddielmi, je to napísané priamo v dokumentácii spotrebitelia >= oddiely tém. Dozvedel som sa to však oveľa neskôr, ako by som chcel. Ak chcete škálovať a mať dvoch spotrebiteľov, potrebujete aspoň dva oddiely. To znamená, že ak ste mali jeden oddiel, v ktorom sa nahromadilo 20 XNUMX správ, a vytvorili ste nový, počet správ sa čoskoro nevyrovná. Preto, aby ste mali dvoch paralelných spotrebiteľov, musíte sa vysporiadať s oddielmi.

monitorovanie

Myslím si, že spôsob, akým to monitorujeme, bude ešte jasnejšie, aké problémy existujú v existujúcom prístupe.

Napríklad vypočítame, koľko produktov v databáze nedávno zmenilo svoj stav a podľa toho by na základe týchto zmien mali nastať udalosti a toto číslo odošleme do nášho monitorovacieho systému. Potom od Kafku dostaneme druhé číslo, koľko udalostí bolo skutočne zaznamenaných. Je zrejmé, že rozdiel medzi týmito dvoma číslami by mal byť vždy nula.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Okrem toho musíte sledovať, ako sa darí producentovi, či zbernica udalostí prijíma správy a ako sa darí spotrebiteľovi. Napríklad v nižšie uvedených grafoch sa nástroju Refund Tool darí dobre, ale BOB má zjavne nejaké problémy (modré vrcholy).

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Už som spomenul oneskorenie skupiny spotrebiteľov. Zhruba povedané, ide o počet neprečítaných správ. Vo všeobecnosti naši spotrebitelia pracujú rýchlo, takže oneskorenie je zvyčajne 0, ale niekedy môže dôjsť ku krátkodobému vrcholu. Kafka to dokáže hneď po vybalení, ale musíte si nastaviť určitý interval.

Existuje projekt dúpäktorá vám poskytne viac informácií o Kafkovi. Jednoducho používa rozhranie API skupiny spotrebiteľov na poskytnutie stavu, ako sa tejto skupine darí. Okrem OK a Neúspešné je tu aj varovanie a vy môžete zistiť, že vaši spotrebitelia nezvládajú tempo výroby – nestíhajú korigovať napísané. Systém je celkom inteligentný a ľahko sa používa.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

Takto vyzerá odpoveď API. Tu je skupina bob-live-fifa, partition refund.update.v1, stav OK, lag 0 - posledný finálny offset taký a taký.

Skúsenosti s vývojom služby Refund Tool s asynchrónnym API na Kafka

monitorovanie updated_at SLA (zaseknutý) Už som spomínal. Produkt sa napríklad zmenil do stavu, že je pripravený na vrátenie. Nainštalujeme Cron, ktorý hovorí, že ak do 5 minút tento objekt nevráti peniaze (vrátime peniaze prostredníctvom platobných systémov veľmi rýchlo), určite sa niečo pokazilo, a to je určite prípad podpory. Preto jednoducho vezmeme Cron, ktorý takéto veci prečíta, a ak sú väčšie ako 0, pošle upozornenie.

Aby som to zhrnul, použitie udalostí je vhodné, keď:

  • informácie potrebuje niekoľko systémov;
  • výsledok spracovania nie je dôležitý;
  • je málo podujatí alebo malých podujatí.

Zdalo by sa, že článok má veľmi špecifickú tému - asynchrónne API na Kafku, ale v súvislosti s tým by som rád odporučil veľa vecí naraz.
Po prvé, ďalšie HighLoad++ musíme počkať do novembra, v apríli bude verzia v Petrohrade a v júni budeme hovoriť o vysokých nákladoch v Novosibirsku.
Po druhé, autor správy Sergej Zaika je členom programového výboru našej novej konferencie o manažmente znalostí. KnowledgeConf. Konferencia je jednodňová, uskutoční sa 26. apríla, no jej program je veľmi intenzívny.
A bude to v máji PHP Rusko и RIT++ (vrátane DevOpsConf) - môžete tam tiež navrhnúť svoju tému, porozprávať sa o svojich skúsenostiach a posťažovať sa na svoje plnené šišky.

Zdroj: hab.com

Pridať komentár