Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Mi kényszeríthet egy olyan nagy céget, mint a Lamoda, egy letisztult folyamattal és több tucat összekapcsolt szolgáltatással, hogy jelentősen megváltoztassa a szemléletmódját? A motiváció teljesen eltérő lehet: a jogalkotástól a minden programozóban rejlő kísérletezési vágyig.

Ez azonban nem jelenti azt, hogy ne számíthatna további előnyökre. Sergey Zaika elmondja, hogy pontosan mit nyerhetsz, ha megvalósítod az eseményvezérelt API-t a Kafkán (néhányald). Minden bizonnyal szó lesz a nagy lövésekről és az érdekes felfedezésekről is - a kísérlet nem nélkülözheti őket.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Jogi nyilatkozat: Ez a cikk egy találkozó anyagán alapul, amelyet Szergej tartott 2018 novemberében a HighLoad++-on. Lamoda Kafkával végzett munka során szerzett élő tapasztalatai nem kevésbé vonzották a hallgatókat, mint az ütemtervben szereplő többi beszámoló. Szerintünk ez kiváló példa arra, hogy mindig lehet és kell is találni hasonló gondolkodású embereket, és a HighLoad++ szervezői továbbra is igyekeznek ennek megfelelő légkört teremteni.

A folyamatról

A Lamoda egy nagy e-kereskedelmi platform, amely saját kapcsolattartó központtal, szállítási szolgáltatással (és számos leányvállalattal), fotóstúdióval, hatalmas raktárral rendelkezik, és mindez saját szoftveren fut. Több tucat fizetési mód létezik, b2b partnerek, akik igénybe vehetik e szolgáltatások egy részét vagy mindegyikét, és szeretnének naprakész információkat tudni termékeikről. Ráadásul a Lamoda az Orosz Föderáción kívül három országban működik, és ott minden kicsit másképp működik. Összességében valószínűleg több mint száz módja van egy új rendelés konfigurálásának, amelyeket a maga módján kell feldolgozni. Mindez több tucat szolgáltatás segítségével működik, amelyek néha nem nyilvánvaló módon kommunikálnak. Létezik egy központi rendszer is, amelynek fő feladata a rendelési állapotok. BOB-nak hívjuk, vele dolgozom.

Refund Tool eseményvezérelt API-val

Az eseményvezérelt szó meglehetősen elcsépelt, kicsit tovább fogjuk részletesebben meghatározni, hogy mit is kell érteni ezen. Kezdem azzal a kontextussal, amelyben úgy döntöttünk, hogy kipróbáljuk az eseményvezérelt API-megközelítést a Kafkában.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Bármely üzletben a vásárlók által fizetett rendeléseken túlmenően előfordul, hogy az üzletnek pénzt kell visszaküldenie, mert a termék nem felelt meg a vásárlónak. Ez egy viszonylag rövid folyamat: szükség esetén pontosítjuk az információkat, és átutaljuk a pénzt.

Ám a visszaszolgáltatás a jogszabályi változások miatt bonyolultabbá vált, ehhez külön mikroszolgáltatást kellett megvalósítanunk.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Motivációnk:

  1. törvény FZ-54 - egyszóval a törvény megköveteli, hogy minden pénzügyletről be kell jelenteni az adóhivatalnak, legyen az bevallás vagy nyugta, meglehetősen rövid, néhány perces SLA-n belül. Mi, mint e-kereskedelmi cég, meglehetősen sok műveletet végzünk. Technikailag ez új felelősséget (és ezáltal új szolgáltatást) és fejlesztéseket jelent az összes érintett rendszerben.
  2. BOB felosztás a vállalat belső projektje, amely a BOB-ot számos nem alapvető felelősség alól mentesíti és általános összetettségét csökkenti.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Ez a diagram a fő Lamoda rendszereket mutatja be. Most a legtöbbjük több egy zsugorodó monolit körül 5-10 mikroszolgáltatásból álló konstelláció. Lassan nőnek, de igyekszünk kicsinyíteni őket, mert a középen kiválasztott töredék kihelyezése ijesztő - nem engedhetjük meg, hogy leessen. Kénytelenek vagyunk minden cserét (nyilak) lefoglalni, és figyelembe kell venni, hogy bármelyikük elérhetetlenné válhat.

A BOB-nak is elég sok cseréje van: fizetési rendszerek, kézbesítési rendszerek, értesítési rendszerek stb.

Technikailag a BOB:

  • ~150k kódsor + ~100k sor teszt;
  • php7.2 + Zend 1 és Symfony Components 3;
  • >100 API és ~50 kimenő integráció;
  • 4 ország saját üzleti logikával.

A BOB telepítése drága és fájdalmas, a kód és a megoldandó problémák mennyisége akkora, hogy senki sem tudja az egészet a fejébe adni. Általában sok oka van az egyszerűsítésnek.

Visszaküldési folyamat

Kezdetben két rendszer vesz részt a folyamatban: BOB és Payment. Most újabb kettő jelenik meg:

  • Fiscalization Service, amely gondoskodik a fiskalizálással és a külső szolgáltatásokkal való kommunikációval kapcsolatos problémákról.
  • Visszatérítési eszköz, amely egyszerűen csak új cseréket tartalmaz, hogy ne növelje a BOB-ot.

Most a folyamat így néz ki:

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

  1. BOB visszatérítési kérelmet kap.
  2. BOB beszél erről a visszatérítési eszközről.
  3. A Visszatérítési eszköz azt mondja a Fizetésnek: „Vissza vissza a pénzt”.
  4. A fizetés visszaadja a pénzt.
  5. A Refund Tool és a BOB szinkronizálja az állapotokat egymással, mert egyelőre mindkettőnek szüksége van rá. Még nem állunk készen arra, hogy teljesen áttérjünk a Visszatérítési eszközre, mivel a BOB-nak van felhasználói felülete, könyvelési jelentései és általában sok olyan adat, amelyet nem lehet olyan könnyen átvinni. Két széken kell ülni.
  6. A fiskalizálási kérelem megszűnik.

Ennek eredményeként a Kafkán egyfajta rendezvénybuszt készítettünk - rendezvény-busz, amin minden elindult. Hurrá, most egyetlen kudarcpontunk van (szarkazmus).

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Az előnyök és hátrányok elég nyilvánvalóak. Készítettünk egy buszt, ami azt jelenti, hogy most már minden szolgáltatás rajta múlik. Ez leegyszerűsíti a tervezést, de egyetlen hibapontot vezet be a rendszerbe. Kafka összeomlik, a folyamat leáll.

Mi az az eseményvezérelt API

Erre a kérdésre jó válasz található Martin Fowler jelentésében (GOTO 2017) "Az eseményvezérelt építészet sokféle jelentése".

Röviden, mit csináltunk:

  1. Csomagolja le az összes aszinkron cserét a következőn keresztül események tárolása. Ahelyett, hogy minden érdeklődő fogyasztót a hálózaton keresztül értesítenénk a státuszváltásról, egy központi tárhely állapotváltozásáról eseményt írunk, a téma iránt érdeklődő fogyasztók pedig mindent elolvasnak, ami onnan megjelenik.
  2. Az esemény ebben az esetben egy értesítés (értesítések), hogy valahol valami megváltozott. Például a rendelés állapota megváltozott. Az a fogyasztó, aki az állapotváltozást kísérő, a bejelentésben nem szereplő adatok iránt érdeklődik, maga is tájékozódhat annak állapotáról.
  3. A maximális lehetőség a teljes körű eseménybeszerzés, államátadás, mely esetben minden, a feldolgozáshoz szükséges információt tartalmaz: honnan jött és milyen állapotba került, pontosan hogyan változtak az adatok stb. A kérdés csak az, hogy mennyire lehet és mennyi információ tárolható.

A Visszatérítési eszköz elindítása részeként a harmadik lehetőséget alkalmaztuk. Ez leegyszerűsítette az eseményfeldolgozást, mivel nem volt szükség részletes információk kinyerésére, valamint kiküszöbölte azt a forgatókönyvet, amelyben minden új esemény a fogyasztóktól érkező tisztázó kérések sorozatát generálja.

Visszatérítési eszköz szolgáltatás nincs betöltve, tehát Kafka inkább a toll íze, mintsem szükséglet. Nem hiszem, hogy ha a visszatérítési szolgáltatásból nagy terhelésű projekt lenne, akkor az üzlet boldog lenne.

Aszinkron csere, ahogy VAN

Az aszinkron cserékhez a PHP részleg általában a RabbitMQ-t használja. A kéréshez összegyűjtöttük az adatokat, sorba állítottuk, és ugyanazon szolgáltatás fogyasztója elolvasta és elküldte (vagy nem küldte el). Magához az API-hoz a Lamoda aktívan használja a Swaggert. Tervezünk egy API-t, leírjuk a Swaggerben, és kliens- és szerverkódot generálunk. Egy kissé továbbfejlesztett JSON RPC 2.0-t is használunk.

Egyes helyeken ESB buszokat használnak, néhány az ActiveMQ-n él, de általában RabbitMQ - szabvány.

Aszinkron csere TO BE

Az esemény-buszon keresztüli csere tervezésekor egy analógia nyomon követhető. Hasonlóan leírjuk a jövőbeli adatcserét az eseménystruktúra leírásán keresztül. A yaml formátum, a kódgenerálást magunknak kellett elvégeznünk, a generátor a specifikáció szerint DTO-kat készít, és megtanítja a klienseket és a szervereket azokkal dolgozni. A generáció két nyelvre megy át - golang és php. Ez segít megőrizni a könyvtárak egységességét. A generátor golang nyelven van írva, ezért kapta a gogi nevet.

Tipikus dolog a Kafkán történõ események beszerzése. Van megoldás a Kafka Confluent fő vállalati verziójából, van nakadi, Zalando domain testvéreink megoldása. A miénk motiváció a vaníliás Kafkával való kezdéshez - ez azt jelenti, hogy szabadon hagyjuk a megoldást addig, amíg el nem döntjük, hogy mindenhol használni fogjuk-e, valamint mozgásteret hagyunk magunknak a fejlesztésekre: szeretnénk támogatást JSON RPC 2.0, generátorok két nyelvre, és lássuk, mi más.

Ironikus, hogy még ilyen szerencsés esetben sem tudjuk hatékonyan kihasználni, amikor van egy nagyjából hasonló vállalkozás, a Zalando, amely nagyjából hasonló megoldást készített.

Az építészeti minta induláskor a következő: közvetlenül Kafkától olvasunk, de csak esemény-buszon keresztül írunk. A Kafkában sok minden készen áll az olvasásra: brókerek, egyensúlyozók, és többé-kevésbé készen áll a vízszintes skálázásra, ezt meg akartam tartani. A felvételt egy Gateway-en, más néven Events-buszon keresztül akartuk befejezni, és itt van, miért.

Rendezvények-busz

Vagy rendezvénybusz. Ez egyszerűen egy állapot nélküli http-átjáró, amely számos fontos szerepet tölt be:

  • Érvényesítés készítése — ellenőrizzük, hogy az események megfelelnek-e az előírásoknak.
  • Eseménymester rendszer, vagyis ez a fő és egyetlen rendszer a cégben, amely választ ad arra a kérdésre, hogy mely események milyen struktúrákkal tekinthetők érvényesnek. Az érvényesítés egyszerűen adattípusokat és felsorolásokat foglal magában a tartalom szigorú meghatározásához.
  • Hash függvény felosztáshoz - a Kafka-üzenet szerkezete kulcs-érték, és a kulcs hash-je alapján számítják ki, hogy hova kerüljön.

Miért

Nagyvállalatnál dolgozunk, letisztult folyamattal. Miért változtatna bármin is? Ez egy kísérlet, és számos előnyt várunk.

1:n+1 csere (egytől sokig)

A Kafka nagyon egyszerűvé teszi az új fogyasztók API-hoz való csatlakoztatását.

Tegyük fel, hogy van egy könyvtára, amelyet egyszerre több rendszerben (és néhány újban is) naprakészen kell tartania. Korábban feltaláltunk egy csomagot, amely megvalósította a set-API-t, és a fő rendszer értesült a fogyasztói címekről. Most a mesterrendszer frissítéseket küld a témához, és akit érdekel, az elolvassa. Megjelent egy új rendszer - regisztráltuk a témához. Igen, csomagban is, de egyszerűbb.

A visszatérítési eszköz esetében, amely egy darab BOB, kényelmes számunkra, ha ezeket a Kafkán keresztül szinkronizáljuk. A fizetés azt mondja, hogy a pénzt visszaküldték: a BOB, az RT tudomást szerzett erről, megváltoztatta az állapotát, a Fiscalization Service tudomást szerzett erről és kiállított egy csekket.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Terveink között szerepel egy egységes Értesítési szolgáltatás létrehozása, amely értesíti az ügyfelet a megrendelésével/visszaküldésével kapcsolatos hírekről. Most ez a felelősség megoszlik a rendszerek között. Elég lesz megtanítanunk az Értesítési Szolgálatot arra, hogy a Kafkától kapjon releváns információkat, és válaszoljon rá (és tiltsa le ezeket az értesítéseket más rendszerekben). Nincs szükség új közvetlen cserékre.

Adatvezérelt

A rendszerek közötti információ átláthatóvá válik – függetlenül attól, hogy milyen „véres vállalkozás” van, és bármennyire dús a lemaradása. A Lamoda Data Analytics részleggel rendelkezik, amely összegyűjti az adatokat a rendszerekből, és újrafelhasználható formába helyezi, mind üzleti, mind intelligens rendszerek számára. A Kafka lehetővé teszi, hogy gyorsan sok adatot adjon át nekik, és naprakészen tartsa az információáramlást.

Replikációs napló

Az üzenetek nem tűnnek el beolvasás után, mint a RabbitMQ esetében. Ha egy esemény elegendő információt tartalmaz a feldolgozáshoz, rendelkezünk az objektum legutóbbi módosításainak előzményeivel, és szükség esetén lehetőségünk van ezeknek a változtatásoknak a végrehajtására.

A replikációs napló tárolási időtartama a témakörbe való írás intenzitásától függ; a Kafka lehetővé teszi a tárolási idő és az adatmennyiség rugalmas korlátozását. Az intenzív témáknál fontos, hogy minden fogyasztónak legyen ideje elolvasni az információt, mielőtt azok eltűnnének, még rövid távú működésképtelenség esetén is. Általában lehetséges az adatok tárolása napok egységei, ami teljesen elég a támogatáshoz.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Ezután egy kis átbeszélés a dokumentációból, azoknak, akik nem ismerik Kafkát (a kép is a dokumentációból van)

Az AMQP-nek sorai vannak: üzeneteket írunk egy sorba a fogyasztó számára. Általában egy sort dolgoz fel egy rendszer ugyanazzal az üzleti logikával. Ha több rendszert kell értesítenie, megtaníthatja az alkalmazást több sorba írásra, vagy konfigurálhatja a cserét a fanout mechanizmussal, amely maga klónozza azokat.

Kafkának hasonló absztrakciója van téma, amelybe üzeneteket ír, de azok olvasás után nem tűnnek el. Alapértelmezés szerint, amikor csatlakozik a Kafkához, megkapja az összes üzenetet, és lehetősége van arra, hogy ott mentse, ahol abbahagyta. Vagyis szekvenciálisan olvassa el, lehet, hogy nem jelöli meg olvasottnak az üzenetet, hanem menti az azonosítót, ahonnan aztán folytathatja az olvasást. Az Ön által beállított azonosítót offsetnek, a mechanizmust pedig commit offsetnek nevezzük.

Ennek megfelelően különböző logikát lehet megvalósítani. Például 4 esetben van BOB-unk különböző országokban - a Lamoda Oroszországban, Kazahsztánban, Ukrajnában és Fehéroroszországban található. Mivel külön vannak telepítve, kissé eltérő konfigurációkkal és saját üzleti logikával rendelkeznek. Az üzenetben jelezzük, hogy melyik országra vonatkozik. Minden országban minden BOB-fogyasztó más-más groupId-vel olvas, és ha nem rájuk vonatkozik az üzenet, akkor kihagyják, pl. azonnal végrehajtja az eltolás +1-et. Ha ugyanazt a témát a Fizetési Szolgáltatásunk olvassa, akkor azt külön csoporttal teszi, így az ellentételezések nem metszik egymást.

A rendezvény követelményei:

  • Az adatok teljessége. Szeretném, ha az eseménynek elegendő adata lenne a feldolgozáshoz.

  • Sértetlenség. Az Events-busra ruházzuk át annak ellenőrzését, hogy az esemény konzisztens-e, és képes-e feldolgozni.
  • A sorrend fontos. Visszatérés esetén kénytelenek vagyunk a történelemmel dolgozni. Az értesítéseknél a rendelés nem számít, ha homogén értesítésekről van szó, akkor az email ugyanaz lesz, függetlenül attól, hogy melyik rendelés érkezett meg előbb. A visszatérítés esetén egyértelmű a folyamat, ha megváltoztatjuk a rendelést, kivételek keletkeznek, a visszatérítés nem jön létre, nem kerül feldolgozásra - más státuszba kerülünk.
  • Következetesség. Van egy üzletünk, és most API helyett eseményeket hozunk létre. Szükségünk van egy módra, hogy gyorsan és olcsón továbbítsuk szolgáltatásainkba az új eseményekről és a meglévők változásairól szóló információkat. Ez egy különálló git-tárolóban és kódgenerátorokban található közös specifikáción keresztül érhető el. Ezért a kliensek és a szerverek a különböző szolgáltatásokban összehangoltak.

Kafka a Lamodában

Három Kafka-telepítésünk van:

  1. Rönkök;
  2. K + F;
  3. Rendezvények-busz.

Ma csak az utolsó pontról beszélünk. Rendezvény-busznál nincs túl nagy telepítésünk - 3 bróker (szerver) és csak 27 téma. Általános szabály, hogy egy téma egy folyamat. De ez egy finom pont, és most ezt fogjuk érinteni.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Fent látható az rps grafikon. A visszatérítési folyamat türkizkék vonallal van jelölve (igen, az X tengelyen), a rózsaszín vonal pedig a tartalomfrissítési folyamatot jelzi.

A Lamoda katalógusa több millió terméket tartalmaz, és az adatok folyamatosan frissülnek. Egyes kollekciók kimennek a divatból, helyettük újak jelennek meg, és folyamatosan új modellek jelennek meg a katalógusban. Igyekszünk megjósolni, mi lesz holnap érdekes vásárlóink ​​számára, ezért folyamatosan vásárolunk új dolgokat, fotózunk és frissítjük a vitrint.

A rózsaszín csúcsok termékfrissítések, vagyis a termékek változásai. Látszik, hogy a srácok fotóztak, fotóztak, aztán megint! — töltött be egy csomag eseményt.

Lamoda Events használati esetek

A felépített architektúrát a következő műveletekhez használjuk:

  • Visszaküldési állapot követése: cselekvésre ösztönzés és állapotkövetés az összes érintett rendszertől. Fizetés, állapotok, fiskalizálás, értesítések. Itt teszteltük a megközelítést, eszközöket készítettünk, összegyűjtöttük az összes hibát, dokumentációt írtunk és elmondtuk kollégáinknak, hogyan kell használni.
  • Termékkártyák frissítése: konfiguráció, metaadatok, jellemzők. Egy rendszer olvas (ami megjelenik), és több ír.
  • E-mail, push és sms: a rendelés felvett, megérkezett a rendelés, elfogadták a visszaküldést stb., rengeteg van.
  • Készlet-, raktárfelújítás — cikkek mennyiségi frissítése, csak számok: raktárba érkezés, visszaküldés. Szükséges, hogy az árufoglaláshoz kapcsolódó összes rendszer a legfrissebb adatokkal működjön. Jelenleg a készletfrissítési rendszer meglehetősen bonyolult, Kafka le fogja egyszerűsíteni.
  • Az adatok elemzése (K+F részleg), ML eszközök, analitika, statisztika. Azt akarjuk, hogy az információ átlátható legyen – a Kafka erre kiválóan alkalmas.

Most az érdekesebb rész az elmúlt hat hónapban történt nagy zökkenőkről és érdekes felfedezésekről.

Tervezési problémák

Tegyük fel, hogy új dolgot akarunk csinálni – például a teljes szállítási folyamatot átadni a Kafkának. A folyamat egy része most a BOB Rendelésfeldolgozásban van megvalósítva. Egy státuszmodell áll a rendelés kézbesítési szolgálathoz való átvitele, a közbenső raktárba költözés stb. mögött. Van egy egész monolit, akár kettő is, plusz egy csomó API-t szenteltek a szállításnak. Sokkal többet tudnak a szállításról.

Ezek hasonló területeknek tűnnek, de a Rendelésfeldolgozás BOB-ban és a Szállítási Rendszer állapota eltérő. Például egyes futárszolgálatok nem közbülső állapotokat küldenek, hanem csak a végső állapotokat: „kézbesítve” vagy „elveszett”. Mások éppen ellenkezőleg, igen részletesen beszámolnak az áruk mozgásáról. Mindenkinek megvannak a saját érvényesítési szabályai: egyesek számára az e-mail érvényes, ami azt jelenti, hogy feldolgozásra kerül; másoknak nem érvényes, de a rendelést akkor is feldolgozzák, mert van egy telefonszám a kapcsolatfelvételhez, és valaki azt mondja, hogy egy ilyen rendelést egyáltalán nem dolgoznak fel.

Adatfolyam

Kafka esetében felmerül az adatáramlás megszervezésének kérdése. Ez a feladat több ponton alapuló stratégia kiválasztását foglalja magában; menjünk végig ezeken.

Egy témában vagy különböző témákban?

Van egy eseményleírásunk. A BOB-ba írjuk, hogy ilyen-olyan rendelést kell szállítani, és feltüntetjük: a rendelés számát, összetételét, néhány cikkszámot és vonalkódot, stb. Amikor az áru megérkezik a raktárba, a szállítmány megkapja az állapotokat, az időbélyegeket és mindent, ami szükséges. De akkor szeretnénk frissítéseket kapni ezekről az adatokról a BOB-ban. Fordított eljárással fogadjuk az adatokat a szállításból. Ez ugyanaz az esemény? Vagy ez egy külön csere, ami megérdemel egy saját témát?

Nagy valószínűséggel nagyon hasonlóak lesznek, és nem alaptalan a kísértés, hogy egy topikot csináljunk, mert a külön téma külön fogyasztókat, külön konfigokat, mindennek külön generációját jelenti. De nem tény.

Új terület vagy új esemény?

De ha ugyanazokat az eseményeket használja, akkor egy másik probléma merül fel. Például nem minden kézbesítő rendszer képes olyan típusú DTO-t generálni, mint a BOB. Elküldjük nekik az azonosítót, de nem mentik el, mert nincs rá szükségük, és az esemény-busz folyamat indítása szempontjából ez a mező kötelező.

Ha bevezetünk egy szabályt az eseménybuszhoz, hogy ez a mező kötelező, akkor kénytelenek vagyunk további érvényesítési szabályokat beállítani a BOB-ban vagy a start eseménykezelőben. Az érvényesítés elkezd terjedni a szolgáltatásban – ez nem túl kényelmes.

Egy másik probléma a fokozatos fejlődés kísértése. Azt mondják, hogy valamit hozzá kell adni az eseményhez, és lehet, ha belegondolunk, ennek egy külön rendezvénynek kellett volna lennie. De a mi rendszerünkben egy külön rendezvény külön téma. Külön téma az egész folyamat, amelyet fentebb leírtam. A fejlesztőnek nagy a kísértése, hogy egyszerűen hozzáadjon egy másik mezőt a JSON-sémához, és újra generálja azt.

A visszatérítések esetében fél év alatt érkeztünk meg a rendezvényre. Volt egy meta-eseményünk, a visszatérítési frissítés, amelyben volt egy típusmező, amely leírja, hogy valójában mi is ez a frissítés. Emiatt „csodálatos” kapcsolóink ​​voltak validátorokkal, akik megmondták, hogyan kell érvényesíteni ezt az eseményt ezzel a típussal.

Eseményverziókészítés

A Kafka üzenetek érvényesítéséhez használhatja Avro, de azonnal rá kellett feküdni és használni kellett a Confluent. Esetünkben óvatosnak kell lennünk a verziószámmal. Nem mindig lehet újraolvasni az üzeneteket a replikációs naplóból, mert a modell „elhagyott”. Alapvetően úgy kell elkészíteni a verziókat, hogy a modell visszafelé kompatibilis legyen: például egy mezőt ideiglenesen nem kötelezővé kell tenni. Ha túl erősek a különbségek, akkor új témában kezdünk írni, és amikor befejezték a régi olvasását, áthelyezünk klienseket.

A partíciók olvasási sorrendje garantált

A Kafkán belüli témák partíciókra vannak osztva. Ez nem túl fontos, amikor entitásokat és tőzsdéket tervezünk, de fontos, amikor eldöntjük, hogyan használjuk és méretezzük.

Szokásos esetben egy témát írsz Kafkában. Alapértelmezés szerint egy partíció van használatban, és a témakör összes üzenete erre kerül. A fogyasztó következésképpen sorban olvassa el ezeket az üzeneteket. Mondjuk most ki kell bővíteni a rendszert, hogy az üzeneteket két különböző fogyasztó olvassa el. Ha például SMS-t küld, akkor megmondhatja Kafkának, hogy hozzon létre egy további partíciót, és Kafka elkezdi két részre osztani az üzeneteket - fele ide, fele ide.

Hogyan osztja meg őket Kafka? Minden üzenetnek van egy törzse (amelyben a JSON-t tároljuk) és egy kulcs. Ehhez a kulcshoz csatolhat egy hash függvényt, amely meghatározza, hogy az üzenet melyik partícióra kerüljön.

A mi esetünkben a visszatérítésnél ez fontos, ha két partíciót veszünk, akkor van esély arra, hogy egy párhuzamos fogyasztó feldolgozza a második eseményt az első előtt és baj lesz. A hash funkció biztosítja, hogy az azonos kulccsal rendelkező üzenetek ugyanarra a partícióra kerüljenek.

Események vs parancsok

Ez egy másik probléma, amellyel találkoztunk. Az esemény egy bizonyos esemény: azt mondjuk, hogy valahol valami történt (valami_történt), például egy tételt töröltek, vagy visszatérítés történt. Ha valaki meghallgatja ezeket az eseményeket, akkor a „cikk törölve” szerint létrejön a visszatérítési entitás, és valahol a beállításokban megjelenik a „visszatérítés megtörtént” szöveg.

De általában, amikor eseményeket tervez, nem hiába akarja megírni őket - abban bízik, hogy valaki elolvassa őket. Nagy a kísértés, hogy ne valami_történt (tétel_törlése, visszatérítés_visszatérítés) írása, hanem valami_kell_megcsinálandó. Például egy cikk készen áll a visszaküldésre.

Egyrészt azt sugallja, hogyan fogják használni az eseményt. Másrészt sokkal kevésbé hangzik úgy, mint egy normál eseménynév. Emellett nincs messze innen a do_something parancs. De nincs garancia arra, hogy valaki elolvassa ezt az eseményt; és ha elolvastad, akkor sikeresen elolvasod; és ha sikeresen elolvastad, akkor csináltál valamit, és az a valami sikeres volt. Abban a pillanatban, amikor egy esemény csinál valamit, szükségessé válik a visszajelzés, és ez probléma.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

A RabbitMQ aszinkron cseréjénél, amikor elolvassa az üzenetet, lépjen a http-re, akkor van válasz - legalábbis azt, hogy az üzenet megérkezett. Amikor Kafkának írsz, van egy üzenet, amit írtál Kafkának, de semmit sem tudsz a feldolgozásról.

Ezért esetünkben be kellett vezetnünk egy válaszeseményt és be kellett állítani a monitorozást, hogy ha ennyi eseményt küldünk, akkor ennyi és ennyi idő után ugyanannyi válaszesemény érkezzen. Ha ez nem történik meg, akkor úgy tűnik, hogy valami elromlott. Például, ha elküldtük az „item_ready_to_refund” eseményt, akkor arra számítunk, hogy visszatérítés jön létre, a pénz visszakerül az ügyfélhez, és elküldik nekünk a „money_refunded” eseményt. De ez nem biztos, ezért monitorozásra van szükség.

árnyalatok

Van egy eléggé nyilvánvaló probléma: ha sorban olvasol egy témából, és van valami rossz üzeneted, akkor a fogyasztó elesik, te pedig nem mész tovább. Szükséged van állítsa le az összes fogyasztót, hajtsa végre az eltolást az olvasás folytatásához.

Tudtunk róla, számoltunk vele, és mégis megtörtént. És ez azért történt, mert az esemény érvényes volt az események-busz szempontjából, az esemény érvényes volt az alkalmazás érvényesítő szempontjából, de nem volt érvényes a PostgreSQL szempontjából, mert egy rendszerünkben A MySQL UNSIGNED INT-vel, az újonnan írt rendszerben pedig csak INT-vel volt a PostgreSQL. Kicsit kisebb a mérete, és az Id nem passzolt. Symfony egy kivétellel meghalt. Természetesen megfogtuk a kivételt, mert bíztunk benne, és ezt az eltolást meg akartuk tenni, de előtte szerettük volna növelni a hibaszámlálót, mivel az üzenet feldolgozása sikertelen volt. Ebben a projektben a számlálók is az adatbázisban vannak, és a Symfony már lezárta a kommunikációt az adatbázissal, és a második kivétel az egész folyamatot megölte, anélkül, hogy esélyt adtak volna az eltolásra.

A szerviz feküdt egy ideig - szerencsére Kafkánál ez nem olyan rossz, mert az üzenetek megmaradnak. Amikor a munka helyreáll, befejezheti az olvasását. Kényelmes.

A Kafka képes tetszőleges eltolás beállítására szerszámozással. Ehhez azonban minden fogyasztót le kell állítani - esetünkben külön kiadást kell készíteni, amelyben nem lesznek fogyasztók, átcsoportosítások. Ezután a Kafkában eltolja az eltolást a szerszámozással, és az üzenet átmegy.

Még egy árnyalat - replikációs napló vs rdkafka.so - projektünk sajátosságaihoz kapcsolódik. PHP-t használunk, és a PHP-ben általában minden könyvtár az rdkafka.so tárolón keresztül kommunikál Kafkával, és akkor van valamilyen burkoló. Lehet, hogy ezek a mi személyes nehézségeink, de kiderült, hogy egyszerűen újraolvasni egy darabot abból, amit már olvastunk, nem olyan egyszerű. Általában szoftverproblémák voltak.

Visszatérve a partíciókkal való munka sajátosságaihoz, ez pontosan meg van írva a dokumentációban fogyasztók >= témapartíciók. De ezt sokkal később tudtam meg, mint szerettem volna. Ha skálázni szeretne és két fogyasztót szeretne, legalább két partícióra van szüksége. Vagyis ha volt egy partíciója, amelyben 20 ezer üzenet halmozódott fel, és csinált egy újat, akkor az üzenetek száma nem fog egyhamar kiegyenlítődni. Ezért ahhoz, hogy két párhuzamos fogyasztó legyen, partíciókkal kell foglalkoznia.

megfigyelés

Úgy gondolom, hogy az ellenőrzés módja még világosabb lesz, hogy milyen problémák vannak a jelenlegi megközelítésben.

Például kiszámoljuk, hogy az adatbázisban lévő termékek közül hány termék változott a közelmúltban állapotán, és ennek megfelelően ezek alapján eseményeknek kellett volna bekövetkezniük, és ezt a számot elküldjük monitoring rendszerünknek. Aztán Kafkától megkapjuk a második számot, hogy valójában hány eseményt rögzítettek. Nyilvánvaló, hogy a két szám közötti különbségnek mindig nullának kell lennie.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Ezenkívül figyelemmel kell kísérnie, hogy a gyártó hogyan teljesít, hogy az események-busz kapott-e üzeneteket, és hogyan jár a fogyasztó. Például az alábbi diagramokon a Refund Tool jól teljesít, de a BOB-nak egyértelműen vannak problémái (kék csúcsok).

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Már említettem a fogyasztói csoportos lemaradást. Nagyjából ez az olvasatlan üzenetek száma. Általánosságban elmondható, hogy fogyasztóink gyorsan dolgoznak, így a késés általában 0, de néha előfordulhat rövid távú csúcs. Kafka ezt a dobozból is megteheti, de be kell állítania egy bizonyos intervallumot.

Van egy projekt Ásamely több információt ad Kafkáról. Egyszerűen a fogyasztói csoport API-t használja, hogy megadja a csoport teljesítményének állapotát. Az OK és Failed mellett van egy figyelmeztetés, és megtudhatja, hogy fogyasztói nem tudnak megbirkózni a gyártás ütemével - nincs idejük lektorálni a leírtakat. A rendszer meglehetősen okos és könnyen használható.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

Így néz ki az API válasz. Itt van a csoport bob-live-fifa, partíció refund.update.v1, állapot OK, lag 0 - az utolsó végső eltolás ilyen és ilyen.

Tapasztalat a Refund Tool szolgáltatás fejlesztésében a Kafka aszinkron API-jával

megfigyelés updated_at SLA (elakadt) már említettem. Például a termék visszaküldésre kész állapotra változott. Telepítjük a Cront, amely azt mondja, hogy ha ez az objektum 5 percen belül nem megy vissza a visszatérítésre (nagyon gyorsan visszaküldjük a pénzt a fizetési rendszereken keresztül), akkor valami biztosan elromlott, és ez mindenképpen támogatási eset. Ezért egyszerűen vesszük a Cron-t, amely beolvassa az ilyen dolgokat, és ha nagyobbak 0-nál, akkor riasztást küld.

Összefoglalva, az események használata akkor kényelmes, ha:

  • információra több rendszernek van szüksége;
  • a feldolgozás eredménye nem fontos;
  • kevés esemény vagy kis esemény van.

Úgy tűnik, hogy a cikknek nagyon konkrét témája van - a Kafka aszinkron API-ja, de ezzel kapcsolatban sok mindent szeretnék egyszerre ajánlani.
Először is, ezután HighLoad ++ novemberig várnunk kell, áprilisban lesz a szentpétervári változat, júniusban pedig a nagy terhelésekről Novoszibirszkben.
Másodszor, a jelentés szerzője, Szergej Zaika új tudásmenedzsment-konferenciánk programbizottságának tagja. KnowledgeConf. A konferencia egynapos, április 26-án lesz, de a programja igen intenzív.
És májusban lesz PHP Oroszország и RIT++ (a DevOpsConf-fal együtt) - ott is javasolhatja a témáját, beszélhet tapasztalatairól és panaszkodik a töltött kúpjaira.

Forrás: will.com

Hozzászólás