Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Co mohlo přinutit tak velkou společnost, jakou je Lamoda, se zefektivněným procesem a desítkami propojených služeb výrazně změnit svůj přístup? Motivace může být úplně jiná: od legislativní až po touhu experimentovat, která je vlastní všem programátorům.

To ale neznamená, že nemůžete počítat s dalšími výhodami. Sergey Zaika vám řekne, co přesně můžete vyhrát, pokud implementujete událostmi řízené API na Kafka (fewald). Řeč určitě bude také o velkých záběrech a zajímavých objevech – bez nich se experiment neobejde.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Prohlášení: Tento článek je založen na materiálech ze setkání, které Sergey uspořádal v listopadu 2018 na HighLoad++. Lamodova živá zkušenost ze spolupráce s Kafkou přitahovala posluchače neméně než jiné reportáže na programu. Myslíme si, že toto je vynikající příklad toho, že vždy můžete a měli byste najít stejně smýšlející lidi, a organizátoři HighLoad++ se budou i nadále snažit vytvářet atmosféru, která k tomu přispívá.

O postupu

Lamoda je velká e-commerce platforma, která má vlastní kontaktní centrum, doručovací službu (a mnoho poboček), fotoateliér, obrovský sklad a to vše běží na vlastním softwaru. Existují desítky platebních metod, b2b partnerů, kteří mohou využívat některé nebo všechny tyto služby a chtějí znát aktuální informace o svých produktech. Lamoda navíc působí kromě Ruské federace ve třech zemích a tam je všechno trochu jinak. Celkem existuje pravděpodobně více než sto způsobů, jak nakonfigurovat novou objednávku, která musí být zpracována po svém. To vše funguje pomocí desítek služeb, které někdy komunikují nesrozumitelnými způsoby. Existuje také centrální systém, jehož hlavní odpovědností jsou stavy objednávek. Říkáme jí BOB, pracuji s ní.

Nástroj pro vrácení peněz s rozhraním API řízeným událostmi

Slovo řízené událostmi je dosti otřepané, o něco dále podrobněji definujeme, co se tím myslí. Začnu kontextem, ve kterém jsme se rozhodli vyzkoušet přístup API řízený událostmi v Kafce.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

V každém obchodě se kromě objednávek, za které zákazníci platí, vyskytnou případy, kdy je obchod povinen vrátit peníze, protože produkt zákazníkovi nevyhovoval. Jedná se o relativně krátký proces: v případě potřeby upřesníme informace a převedeme peníze.

Jenže návrat se kvůli změnám v legislativě zkomplikoval a museli jsme pro něj implementovat samostatnou mikroslužbu.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Naše motivace:

  1. Zákon FZ-54 - zkrátka zákon vyžaduje nahlásit finančnímu úřadu každou peněžní transakci, ať už vratku nebo účtenku, v poměrně krátkém SLA v řádu minut. My jako e-commerce společnost provádíme poměrně hodně operací. Technicky to znamená novou odpovědnost (a tedy i novou službu) a vylepšení všech zúčastněných systémů.
  2. BOB rozdělení je interním projektem společnosti, který má BOB zbavit velkého množství vedlejších povinností a snížit jeho celkovou složitost.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Tento diagram ukazuje hlavní systémy Lamoda. Nyní jich je více konstelace 5-10 mikroslužeb kolem zmenšujícího se monolitu. Pomalu rostou, ale snažíme se je zmenšit, protože rozmístění úlomku vybraného uprostřed je děsivé - nesmíme dovolit, aby spadl. Všechny výměny (šipky) jsme nuceni rezervovat a počítat s tím, že se některá z nich může ukázat jako nedostupná.

BOB má také poměrně hodně burz: platební systémy, doručovací systémy, oznamovací systémy atd.

Technicky BOB je:

  • ~150 tisíc řádků kódu + ~100 tisíc řádků testů;
  • php7.2 + Zend 1 & Symfony Components 3;
  • >100 API & ~50 odchozích integrací;
  • 4 země s vlastní obchodní logikou.

Nasazení BOB je drahé a bolestivé, množství kódu a problémů, které řeší, je takové, že si to nikdo všechno nevloží do hlavy. Obecně existuje mnoho důvodů, proč to zjednodušit.

Proces vrácení

Zpočátku jsou do procesu zapojeny dva systémy: BOB a Payment. Nyní se objevují další dva:

  • Fiscalization Service, která se postará o problémy s fiskalizací a komunikací s externími službami.
  • Refund Tool, který prostě obsahuje nové výměny, aby nenafoukl BOB.

Nyní proces vypadá takto:

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

  1. BOB obdrží žádost o vrácení peněz.
  2. BOB mluví o tomto nástroji pro vrácení peněz.
  3. Nástroj pro vrácení peněz říká platbě: „Vraťte peníze“.
  4. Platba vrací peníze.
  5. Refund Tool a BOB synchronizují stavy mezi sebou, protože to zatím oba potřebují. Ještě nejsme připraveni úplně přejít na Refund Tool, protože BOB má uživatelské rozhraní, reporty pro účetnictví a obecně spoustu dat, která nelze tak snadno přenést. Musíte sedět na dvou židlích.
  6. Požadavek na fiskalizaci zmizí.

Ve výsledku jsme na Kafce udělali jakýsi event bus - event-bus, na kterém vše začalo. Hurá, teď máme jediný bod selhání (sarkasmus).

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Výhody a nevýhody jsou celkem zřejmé. Udělali jsme autobus, což znamená, že teď na něm závisí všechny služby. To zjednodušuje návrh, ale vnáší do systému jediný bod selhání. Kafka se zhroutí, proces se zastaví.

Co je rozhraní API řízené událostmi

Dobrá odpověď na tuto otázku je ve zprávě Martina Fowlera (GOTO 2017) „Mnoho významů událostmi řízené architektury“.

Stručně, co jsme udělali:

  1. Zabalte všechny asynchronní výměny přes ukládání událostí. Místo toho, abychom každého zainteresovaného spotřebitele informovali o změně stavu v síti, napíšeme událost o změně stavu do centralizovaného úložiště a spotřebitelé, kteří se o dané téma zajímají, čtou vše, co se odtud objeví.
  2. Událostí je v tomto případě oznámení (oznámení), že se někde něco změnilo. Změnil se například stav objednávky. Spotřebitel, který má zájem o některé údaje doprovázející změnu stavu, které nejsou uvedeny v oznámení, si její stav může zjistit sám.
  3. Maximální možností je plnohodnotný zdroj událostí, státní převod, která událost obsahuje všechny informace potřebné pro zpracování: odkud a do jakého stavu se dostala, jak přesně se data změnila atd. Otázkou je pouze proveditelnost a množství informací, které si můžete dovolit uložit.

V rámci spuštění Nástroje pro vrácení peněz jsme využili třetí možnost. Toto zjednodušilo zpracování událostí, protože nebylo potřeba extrahovat podrobné informace, a navíc eliminovalo scénář, kdy každá nová událost generuje výbuch objasňujících požadavků od spotřebitelů.

Nástroj pro vrácení peněz nenačteno, takže Kafka tam je spíš chuť pera než nutnost. Nemyslím si, že kdyby se služba vrácení peněz stala projektem s vysokým zatížením, obchod by byl šťastný.

Asynchronní výměna JAK JE

Pro asynchronní výměny používá oddělení PHP obvykle RabbitMQ. Shromáždili jsme data pro požadavek, zařadili je do fronty a spotřebitel stejné služby si je přečetl a odeslal (nebo neodeslal). Pro samotné API Lamoda aktivně používá Swagger. Navrhneme API, popíšeme ho v Swaggeru a vygenerujeme klientský a serverový kód. Používáme také mírně vylepšený JSON RPC 2.0.

Na některých místech se používají sběrnice ESB, některé žijí na activeMQ, ale obecně RabbitMQ - standard.

Asynchronní výměna TO BE

Při navrhování výměny přes sběrnici událostí lze vysledovat analogii. Podobně popisujeme budoucí výměnu dat prostřednictvím popisu struktury událostí. Formát yaml, generování kódu jsme si museli udělat sami, generátor vytváří DTO dle specifikace a učí klienty a servery s nimi pracovat. Generace jde do dvou jazyků - golang a php. To pomáhá udržovat knihovny konzistentní. Generátor je napsán v golangu, proto dostal jméno gogi.

Event-sourcing na Kafkovi je typická věc. Existuje řešení z hlavní podnikové verze Kafka Confluent, existuje nakadi, řešení od našich doménových bratrů Zalando. Náš motivace začít s vanilkovým Kafkou - to znamená ponechat řešení volnost, dokud se definitivně nerozhodneme, zda ho budeme všude používat, a také si ponechat prostor pro manévrování a vylepšení: chceme podporu pro naše JSON RPC 2.0, generátory pro dva jazyky a uvidíme, co ještě.

Je ironií, že ani v tak šťastném případě, kdy existuje zhruba podobný byznys Zalando, který udělal zhruba podobné řešení, ho nedokážeme efektivně využít.

Architektonický vzor při spuštění je následující: čteme přímo od Kafky, ale píšeme pouze prostřednictvím sběrnice událostí. V Kafkovi je toho ke čtení připraveno hodně: makléři, balancery a je to víceméně připravené na horizontální škálování, tohle jsem chtěl zachovat. Chtěli jsme záznam nahrát přes jednu Gateway alias Events-bus, a tady je důvod.

Akce-bus

Nebo eventový autobus. Toto je jednoduše bezstavová http brána, která přebírá několik důležitých rolí:

  • Produkce validace — kontrolujeme, zda akce splňují naše specifikace.
  • Master systém událostí, to znamená, že se jedná o hlavní a jediný systém ve společnosti, který odpovídá na otázku, které události s jakými strukturami jsou považovány za platné. Ověření jednoduše zahrnuje datové typy a výčty, které přesně specifikují obsah.
  • Hashovací funkce pro sharding - struktura zprávy Kafka je klíč-hodnota a pomocí hashe klíče se vypočítá, kam ji umístit.

Proč

Pracujeme ve velké společnosti se zefektivněným procesem. Proč něco měnit? Toto je experimenta očekáváme, že sklidíme několik výhod.

1:n+1 výměn (jedna k mnoha)

Kafka velmi usnadňuje připojení nových spotřebitelů k API.

Řekněme, že máte adresář, který potřebujete udržovat aktuální v několika systémech najednou (a v některých nových). Dříve jsme vynalezli balíček, který implementoval set-API a hlavní systém byl informován o adresách spotřebitelů. Nyní hlavní systém posílá aktualizace tématu a každý, kdo má zájem, si to přečte. Objevil se nový systém – přihlásili jsme ho do tématu. Ano, také svazek, ale jednodušší.

V případě refundačního nástroje, který je součástí BOB, je pro nás výhodné je udržovat synchronizované prostřednictvím Kafky. Platba říká, že peníze byly vráceny: BOB, RT se o tom dozvěděli, změnili své stavy, služba Fiscalization Service se o tom dozvěděla a vystavila šek.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Máme v plánu vytvořit jednotnou Notifikační službu, která by klienta informovala o novinkách ohledně jeho objednávky/vrácení zboží. Nyní je tato odpovědnost rozdělena mezi systémy. Bude nám stačit naučit Notifikační službu zachytit relevantní informace od Kafky a reagovat na ně (a zakázat tato upozornění v jiných systémech). Žádné nové přímé výměny nebudou vyžadovány.

Data-řízený

Informace mezi systémy se stanou transparentní – bez ohledu na to, jaký máte „krvavý podnik“ a bez ohledu na to, jak velké jsou vaše nevyřízené položky. Lamoda má oddělení Data Analytics, které shromažďuje data ze systémů a dává je do znovu použitelné formy jak pro podnikání, tak pro inteligentní systémy. Kafka vám umožňuje rychle jim poskytnout spoustu dat a udržovat tok informací aktuální.

Protokol replikace

Zprávy po přečtení nezmizí, jako v RabbitMQ. Když událost obsahuje dostatek informací pro zpracování, máme historii nedávných změn objektu a v případě potřeby možnost tyto změny aplikovat.

Doba uložení replikačního logu závisí na intenzitě zápisu do tohoto tématu, Kafka umožňuje flexibilně nastavit limity doby uložení a objemu dat. U intenzivních témat je důležité, aby všichni spotřebitelé měli čas si informace přečíst, než zmizí, a to i v případě krátkodobé nefunkčnosti. Obvykle je možné ukládat data pro jednotky dnů, což je na podporu docela dost.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Dále malé převyprávění dokumentace, pro ty, kteří Kafku neznají (obrázek je také z dokumentace)

AMQP má fronty: píšeme zprávy do fronty pro spotřebitele. Jedna fronta je obvykle zpracovávána jedním systémem se stejnou obchodní logikou. Pokud potřebujete upozornit několik systémů, můžete aplikaci naučit zapisovat do několika front nebo nakonfigurovat výměnu pomocí mechanismu fanout, který je sám naklonuje.

Kafka má podobnou abstrakci aktuální, do kterého píšete zprávy, které ale po přečtení nezmizí. Ve výchozím nastavení, když se připojíte ke Kafce, obdržíte všechny zprávy a máte možnost uložit tam, kde jste skončili. To znamená, že čtete postupně, nemůžete zprávu označit jako přečtenou, ale uložíte si id, ze kterého pak můžete pokračovat ve čtení. ID, na kterém jste se usadili, se nazývá offset a mechanismus je posun potvrzení.

V souladu s tím lze implementovat odlišnou logiku. Například máme BOB ve 4 případech pro různé země - Lamoda je v Rusku, Kazachstánu, Ukrajině, Bělorusku. Protože jsou nasazeny samostatně, mají mírně odlišné konfigurace a vlastní obchodní logiku. Ve zprávě uvádíme, které země se týká. Každý spotřebitel BOB v každé zemi čte s jiným groupId a pokud se ho zpráva netýká, přeskočí ji, tzn. okamžitě provede offset +1. Pokud stejné téma čte naše Platební služba, pak tak činí se samostatnou skupinou, a proto se offsety nekříží.

Požadavky na akci:

  • Úplnost dat. Přál bych si, aby událost měla dostatek dat, aby ji bylo možné zpracovat.

  • Integrita Na Events-bus delegujeme ověření, že událost je konzistentní a dokáže ji zpracovat.
  • Pořadí je důležité. V případě návratu jsme nuceni pracovat s historií. U notifikací není pořadí důležité, pokud se jedná o homogenní notifikace, email bude stejný bez ohledu na to, která objednávka dorazila jako první. V případě vrácení peněz je postup jasný, změníme-li objednávku, vzniknou výjimky, refundace se nevytvoří ani nezpracuje - skončíme v jiném stavu.
  • Konzistence. Máme obchod a teď místo API vytváříme události. Potřebujeme způsob, jak rychle a levně předávat informace o nových událostech a změnách stávajících do našich služeb. Toho je dosaženo prostřednictvím společné specifikace v samostatném úložišti git a generátorech kódu. Klienti a servery v různých službách jsou proto koordinováni.

Kafka v Lamodě

Máme tři Kafkovy instalace:

  1. protokoly;
  2. výzkum a vývoj;
  3. Akce-bus.

Dnes mluvíme pouze o posledním bodě. Na events-bus nemáme příliš velké instalace - 3 brokeři (servery) a pouze 27 témat. Zpravidla jedno téma je jeden proces. Ale to je jemný bod a my se ho nyní dotkneme.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Nahoře je graf otáček. Proces vrácení peněz je označen tyrkysovou čarou (ano, ta na ose X) a růžová čára je proces aktualizace obsahu.

Katalog Lamoda obsahuje miliony produktů a data jsou neustále aktualizována. Některé kolekce vycházejí z módy, vycházejí nové, které je nahrazují, a v katalogu se neustále objevují nové modely. Snažíme se předvídat, co bude pro naše zákazníky zítra zajímavé, proto neustále nakupujeme nové věci, fotíme je a aktualizujeme vitrínu.

Růžové vrcholy jsou aktualizace produktů, tedy změny v produktech. Je vidět, že kluci fotili, fotili a pak zase! — naložil balíček událostí.

Případy použití Lamoda Events

Konstruovanou architekturu používáme pro následující operace:

  • Sledování stavu vrácení: výzvy k akci a sledování stavu ze všech zapojených systémů. Platba, stavy, fiskalizace, notifikace. Zde jsme testovali přístup, vyrobili nástroje, shromáždili všechny chyby, napsali dokumentaci a řekli kolegům, jak jej používat.
  • Aktualizace produktových karet: konfigurace, metadata, charakteristiky. Jeden systém čte (který zobrazuje) a několik zapisuje.
  • Email, push a sms: objednávka vyzvednuta, objednávka dorazila, vrácení přijato atd., je jich hodně.
  • Sklad, obnova skladu — kvantitativní aktualizace položek, jen čísla: příchod na sklad, vrácení. Je nutné, aby všechny systémy spojené s rezervací zboží fungovaly s nejaktuálnějšími daty. Aktuálně je systém aktualizace akcií poměrně složitý, Kafka jej zjednoduší.
  • Analýza dat (oddělení výzkumu a vývoje), nástroje ML, analytika, statistika. Chceme, aby informace byly transparentní – Kafka se k tomu dobře hodí.

Nyní ta zajímavější část o velkých nerovnostech a zajímavých objevech, ke kterým došlo za posledních šest měsíců.

Problémy s designem

Řekněme, že chceme udělat novou věc – například přenést celý proces doručení do Kafky. Nyní je část procesu implementována ve Zpracování objednávek v BOB. Za předáním objednávky doručovací službě, přesunem na mezisklad a podobně stojí stavový model. Existuje celý monolit, dokonce dva, plus spousta API vyhrazených pro doručování. Vědí mnohem více o doručení.

Zdá se, že jde o podobné oblasti, ale Zpracování objednávek v BOB a Expediční systém mají různé stavy. Některé kurýrní služby například neposílají mezistavy, ale pouze konečné: „doručeno“ nebo „ztraceno“. Jiní naopak velmi podrobně informují o pohybu zboží. Každý má svá vlastní pravidla ověřování: pro některé je e-mail platný, což znamená, že bude zpracován; pro ostatní to neplatí, ale objednávka se stejně vyřídí, protože je tam telefonní číslo na kontakt a někdo řekne, že taková objednávka nebude vyřízena vůbec.

Datový tok

V případě Kafky vyvstává otázka organizace datového toku. Tento úkol zahrnuje výběr strategie na základě několika bodů; pojďme si je všechny projít.

V jednom tématu nebo v různých?

Máme specifikaci akce. V BOB napíšeme, že takovou a takovou objednávku je třeba dodat, a uvedeme: číslo objednávky, její složení, některé SKU a čárové kódy atd. Když zboží dorazí na sklad, dodávka bude moci přijímat stavy, časová razítka a vše, co je potřeba. Ale pak chceme dostávat aktualizace těchto dat v BOB. Máme opačný proces přijímání dat od doručení. Je to stejná událost? Nebo jde o samostatnou burzu, která si zaslouží vlastní téma?

S největší pravděpodobností budou velmi podobné a pokušení vytvořit jedno téma není neopodstatněné, protože samostatné téma znamená samostatné spotřebitele, samostatné konfigurace, samostatnou generaci toho všeho. Ale ne fakt.

Nový obor nebo nová akce?

Pokud ale použijete stejné události, pak nastává další problém. Například ne všechny doručovací systémy mohou generovat druh DTO, který může generovat BOB. Pošleme jim ID, ale oni si ho neuloží, protože ho nepotřebují, a z hlediska spuštění procesu sběrnice událostí je toto pole povinné.

Pokud zavedeme pravidlo pro sběrnici událostí, že toto pole je povinné, pak jsme nuceni nastavit další ověřovací pravidla v BOB nebo v obslužné rutině události start. Validace se začíná šířit po celé službě - to není příliš pohodlné.

Dalším problémem je pokušení postupného rozvoje. Je nám řečeno, že je třeba k události něco přidat a možná, když se nad tím zamyslíme, měla to být samostatná akce. Ale v našem schématu je samostatná událost samostatným tématem. Samostatným tématem je celý proces, který jsem popsal výše. Vývojář je v pokušení jednoduše přidat další pole do schématu JSON a znovu jej vygenerovat.

V případě refundací jsme na akci akcí dorazili za půl roku. Měli jsme jednu metaudálost nazvanou aktualizace vrácení peněz, která měla pole typu popisující, co tato aktualizace ve skutečnosti byla. Z tohoto důvodu jsme měli „báječné“ přepínače s validátory, kteří nám řekli, jak tuto událost ověřit pomocí tohoto typu.

Verze událostí

K ověření zpráv v Kafka můžete použít Avro, ale bylo nutné si na něj hned lehnout a použít Confluent. V našem případě musíme být opatrní s verzováním. Nebude vždy možné znovu přečíst zprávy z protokolu replikace, protože model „odešel“. V zásadě se ukazuje, že se sestavují verze tak, aby byl model zpětně kompatibilní: například udělejte pole dočasně nepovinné. Pokud jsou rozdíly příliš silné, začneme psát nové téma a převedeme klienty, když dočtou to staré.

Zaručené pořadí čtení oddílů

Témata uvnitř Kafky jsou rozdělena do oddílů. To není příliš důležité, když navrhujeme entity a burzy, ale je to důležité při rozhodování, jak to spotřebovat a škálovat.

V obvyklém případě napíšete jedno téma do Kafky. Ve výchozím nastavení se používá jeden oddíl a všechny zprávy v tomto tématu směřují do něj. A spotřebitel následně čte tyto zprávy postupně. Řekněme, že nyní potřebujeme rozšířit systém tak, aby zprávy byly čteny dvěma různými spotřebiteli. Pokud například posíláte SMS, můžete říct Kafkovi, aby vytvořil další oddíl, a Kafka začne rozdělovat zprávy na dvě části – půl sem, půl sem.

Jak je Kafka rozděluje? Každá zpráva má tělo (ve kterém ukládáme JSON) a klíč. K tomuto klíči můžete připojit hashovací funkci, která určí, do kterého oddílu zpráva půjde.

V našem případě s refundacemi je to důležité, pokud vezmeme dva oddíly, pak je šance, že paralelní spotřebitel zpracuje druhou událost před první a bude problém. Hašovací funkce zajišťuje, že zprávy se stejným klíčem skončí ve stejném oddílu.

Události vs příkazy

To je další problém, na který jsme narazili. Událost je určitá událost: říkáme, že se někde něco stalo (něco_se stalo), například byla zrušena položka nebo došlo k vrácení peněz. Pokud někdo poslouchá tyto události, pak podle „položka zrušena“ se vytvoří entita pro vrácení peněz a někde v nastavení bude napsáno „došlo k vrácení peněz“.

Ale obvykle, když navrhujete události, nechcete je psát zbytečně - spoléháte na to, že je někdo bude číst. Existuje velké pokušení napsat ne něco_ se stalo (item_canceled, refund_refunded), ale something_should_be_done. Položka je například připravena k vrácení.

Na jedné straně naznačuje, jak bude akce využita. Na druhou stranu to zní mnohem méně jako normální název události. Kromě toho to odtud není daleko k příkazu udělej něco. Ale nemáte žádnou záruku, že tuto událost někdo četl; a pokud to čtete, pak to čtete úspěšně; a pokud jste to přečetli úspěšně, pak jste něco udělali, a to se něco povedlo. Ve chvíli, kdy se z události stane něco udělat, je potřeba zpětná vazba, a to je problém.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

V asynchronní výměně v RabbitMQ, když čtete zprávu, přejděte na http, máte odpověď - alespoň že zpráva byla přijata. Když píšete Kafkovi, je tam zpráva, že jste psal Kafkovi, ale nevíte nic o tom, jak byla zpracována.

Proto jsme v našem případě museli zavést událost odezvy a nastavit sledování tak, že pokud se odešle tolik událostí, po takové a takové době by měl dorazit stejný počet událostí odezvy. Pokud se tak nestane, zdá se, že se něco pokazilo. Pokud jsme například odeslali událost „item_ready_to_refund“, očekáváme, že bude vytvořena refundace, peníze budou vráceny klientovi a událost „money_refunded“ bude odeslána nám. To ale není jisté, proto je nutné sledování.

Nuance

Existuje poměrně zřejmý problém: pokud čtete od tématu postupně a máte nějakou špatnou zprávu, spotřebitel padne a vy už nepůjdete. Potřebuješ zastavit všechny spotřebitele, potvrďte offset dále a pokračujte ve čtení.

Věděli jsme o tom, počítali jsme s tím, a přesto se to stalo. A to se stalo, protože událost byla platná z pohledu událostí-sběrnice, událost platila z pohledu validátoru aplikace, ale nebyla platná z pohledu PostgreSQL, protože v našem jednom systému MySQL s UNSIGNED INT a v nově napsaném systému měl PostgreSQL právě s INT. Jeho velikost je o něco menší a ID se nevešlo. Symfony zemřel až na výjimku. Výjimku jsme samozřejmě zachytili, protože jsme na ni spoléhali a chystali se provést tento offset, ale předtím jsme chtěli zvýšit počítadlo problémů, protože zpráva byla zpracována neúspěšně. Čítače v tomto projektu jsou také v databázi a Symfony již ukončilo komunikaci s databází a druhá výjimka zabila celý proces bez šance na potvrzení offsetu.

Služba na nějakou dobu ulehla - naštěstí to s Kafkou není tak špatné, protože zprávy zůstávají. Po obnovení práce je můžete dočíst. Je to pohodlné.

Kafka má schopnost nastavit libovolný offset pomocí nástrojů. Chcete-li to však udělat, musíte zastavit všechny spotřebitele - v našem případě připravit samostatné vydání, ve kterém nebudou žádní spotřebitelé, přemístění. Pak v Kafkovi můžete posunout offset pomocí nástrojů a zpráva projde.

Další nuance - replikační protokol vs rdkafka.so - souvisí se specifiky našeho projektu. Používáme PHP a v PHP zpravidla všechny knihovny komunikují s Kafkou přes repozitář rdkafka.so a pak je tam nějaký obal. Možná jsou to naše osobní potíže, ale ukázalo se, že jednoduše znovu přečíst kus toho, co jsme již četli, není tak snadné. Obecně se vyskytly softwarové problémy.

Vrátíme-li se ke specifikům práce s oddíly, je to napsáno přímo v dokumentaci spotřebitelé >= tématické oddíly. To jsem se ale dozvěděl mnohem později, než bych si přál. Pokud chcete škálovat a mít dva spotřebitele, potřebujete alespoň dva oddíly. To znamená, že pokud jste měli jeden oddíl, ve kterém se nahromadilo 20 tisíc zpráv, a vytvořili jste nový, počet zpráv se brzy nevyrovná. Proto, abyste měli dva paralelní spotřebitele, musíte se vypořádat s oddíly.

Sledování

Myslím, že způsob, jakým to sledujeme, bude ještě jasnější, jaké problémy existují ve stávajícím přístupu.

Například spočítáme, kolik produktů v databázi v poslední době změnilo svůj stav, a podle toho měly na základě těchto změn nastat události, a toto číslo odešleme do našeho monitorovacího systému. Od Kafky pak dostáváme druhé číslo, kolik událostí bylo skutečně zaznamenáno. Je zřejmé, že rozdíl mezi těmito dvěma čísly by měl být vždy nula.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Kromě toho musíte sledovat, jak se daří producentovi, zda sběrnice událostí přijímá zprávy a jak se daří spotřebiteli. Například v níže uvedených grafech si Refund Tool vede dobře, ale BOB má zjevně nějaké problémy (modré vrcholy).

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Již jsem zmínil zpoždění spotřebitelské skupiny. Zhruba řečeno jde o počet nepřečtených zpráv. Obecně platí, že naši spotřebitelé pracují rychle, takže zpoždění je obvykle 0, ale někdy může dojít ke krátkodobému vrcholu. Kafka to umí hned po vybalení, ale musíte si nastavit určitý interval.

Existuje projekt Doupěkterá vám poskytne více informací o Kafkovi. Jednoduše používá rozhraní API skupiny spotřebitelů, aby poskytlo stav, jak se této skupině daří. Kromě OK a Failed je zde varování a můžete zjistit, že vaši spotřebitelé nezvládají tempo výroby - nemají čas na korekturu napsaného. Systém je docela chytrý a snadno se používá.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Takto vypadá odpověď API. Zde je skupina bob-live-fifa, partition refund.update.v1, stav OK, lag 0 - poslední finální offset takový a takový.

Zkušenosti s vývojem služby Refund Tool s asynchronním API na Kafka

Sledování updated_at SLA (zaseknutý) Už jsem zmínil. Například se produkt změnil do stavu, že je připraven k vrácení. Nainstalujeme Cron, který říká, že pokud do 5 minut tento objekt nešel vrátit peníze (vracíme peníze prostřednictvím platebních systémů velmi rychle), pak se určitě něco pokazilo, a to je rozhodně případ podpory. Proto prostě vezmeme Cron, který takové věci čte, a pokud jsou větší než 0, pošle upozornění.

Abych to shrnul, použití událostí je vhodné, když:

  • informace potřebuje několik systémů;
  • výsledek zpracování není důležitý;
  • je málo akcí nebo malých akcí.

Zdálo by se, že článek má velmi specifické téma - asynchronní API na Kafku, ale v souvislosti s tím bych rád doporučil spoustu věcí najednou.
První, další HighLoad++ musíme počkat do listopadu, v dubnu bude verze z Petrohradu a v červnu se budeme bavit o vysokých nákladech v Novosibirsku.
Za druhé, autor zprávy, Sergej Zaika, je členem programového výboru naší nové konference o řízení znalostí. KnowledgeConf. Konference je jednodenní, uskuteční se 26. dubna, ale její program je velmi intenzivní.
A bude to v květnu PHP Rusko и RIT++ (včetně DevOpsConf) – můžete zde také navrhovat své téma, mluvit o svých zkušenostech a stěžovat si na své plněné šišky.

Zdroj: www.habr.com

Přidat komentář