Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Što bi moglo natjerati tako veliku tvrtku kao što je Lamoda, s moderniziranim procesom i desecima međusobno povezanih usluga, da značajno promijeni svoj pristup? Motivacija može biti potpuno drugačija: od zakonodavne do želje za eksperimentiranjem svojstvene svim programerima.

Ali to ne znači da ne možete računati na dodatne pogodnosti. Sergey Zaika će vam reći što točno možete osvojiti ako implementirate API vođen događajima na Kafki (nekoliko nekoliko). Svakako će biti riječi i o velikim hitovima i zanimljivim otkrićima - bez njih eksperiment ne može.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Odricanje od odgovornosti: Ovaj se članak temelji na materijalima sa sastanka koji je Sergey održao u studenom 2018. na HighLoad++. Lamodino iskustvo rada s Kafkom uživo privuklo je slušatelje ništa manje od drugih izvješća na rasporedu. Smatramo da je ovo izvrstan primjer da se uvijek mogu i trebaju naći istomišljenici, a organizatori HighLoad++-a će se i dalje truditi stvoriti atmosferu koja tome pogoduje.

O procesu

Lamoda je velika platforma za e-trgovinu koja ima vlastiti kontakt centar, dostavnu službu (i mnoge podružnice), foto studio, ogromno skladište, a sve to radi na vlastitom softveru. Postoje deseci načina plaćanja, b2b partneri koji mogu koristiti neke ili sve od ovih usluga i žele znati ažurirane informacije o njihovim proizvodima. Osim toga, Lamoda osim Ruske Federacije posluje u tri zemlje i tamo je sve malo drugačije. Ukupno postoji vjerojatno više od stotinu načina za konfiguriranje novog naloga, koji se mora obraditi na svoj način. Sve to funkcionira uz pomoć desetaka servisa koji ponekad komuniciraju na neočite načine. Postoji i središnji sustav čija su glavna odgovornost statusi naloga. Zovemo je BOB, radim s njom.

Alat za povrat s API-jem vođenim događajima

Riječ vođena događajima prilično je otrcana; malo dalje ćemo detaljnije definirati što se pod tim podrazumijeva. Počet ću s kontekstom u kojem smo odlučili isprobati API pristup vođen događajima u Kafki.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

U svakoj trgovini, osim narudžbi koje kupci plaćaju, postoje trenuci kada trgovina mora vratiti novac jer proizvod nije odgovarao kupcu. To je relativno kratak proces: razjašnjavamo informacije, ako je potrebno, i prenosimo novac.

No povrat se zakomplicirao zbog promjena u zakonodavstvu, pa smo za njega morali implementirati zasebnu mikroservis.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Naša motivacija:

  1. Zakon FZ-54 - ukratko, zakon nalaže izvješćivanje porezne uprave o svakoj novčanoj transakciji, bilo da se radi o povratu ili primitku, unutar prilično kratkog SLA od nekoliko minuta. Mi, kao tvrtka za e-trgovinu, obavljamo dosta operacija. Tehnički, to znači novu odgovornost (a time i novu uslugu) i poboljšanja u svim uključenim sustavima.
  2. BOB split je interni projekt tvrtke za oslobađanje BOB-a od velikog broja sporednih odgovornosti i smanjenje njegove ukupne složenosti.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Ovaj dijagram prikazuje glavne Lamoda sustave. Sada ih je većina više konstelacija od 5-10 mikroservisa oko monolita koji se smanjuje. Oni polako rastu, ali pokušavamo ih smanjiti, jer je postavljanje fragmenta odabranog u sredini zastrašujuće - ne smijemo dopustiti da padne. Prisiljeni smo rezervirati sve mjenjačnice (strelice) i uzeti u obzir činjenicu da se neka od njih može pokazati nedostupnom.

BOB također ima dosta razmjena: sustave plaćanja, sustave dostave, sustave obavijesti itd.

Tehnički BOB je:

  • ~150k redaka koda + ~100k redaka testova;
  • php7.2 + Zend 1 & Symfony Components 3;
  • >100 API-ja & ~50 izlaznih integracija;
  • 4 zemlje sa svojom poslovnom logikom.

Implementacija BOB-a je skupa i bolna, količina koda i problema koje rješava je tolika da si nitko ne može sve to staviti u glavu. Općenito, postoji mnogo razloga da se to pojednostavi.

Proces povrata

U početku su dva sustava uključena u proces: BOB i Payment. Sada se pojavljuju još dvije:

  • Služba za fiskalizaciju koja će rješavati probleme fiskalizacije i komunikacije s vanjskim servisima.
  • Alat za povrat sredstava, koji jednostavno sadrži nove razmjene kako ne bi napuhao BOB.

Sada proces izgleda ovako:

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

  1. BOB prima zahtjev za povrat novca.
  2. BOB govori o ovom alatu za povrat novca.
  3. Alat za povrat novca govori Plaćanju: "Vratite novac."
  4. Plaćanje vraća novac.
  5. Refund Tool i BOB međusobno sinkroniziraju statuse, jer za sada trebaju i jedni i drugi. Nismo još spremni potpuno prijeći na Refund Tool, jer BOB ima UI, izvješća za računovodstvo i općenito puno podataka koji se ne mogu tako lako prenijeti. Morate sjediti na dvije stolice.
  6. Ode zahtjev za fiskalizaciju.

Kao rezultat, napravili smo svojevrsni event bus na Kafku - event-bus, na kojem je sve počelo. Hura, sada imamo jednu točku neuspjeha (sarkazam).

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Prednosti i mane su prilično očite. Napravili smo autobus, što znači da sada sve službe ovise o njemu. Ovo pojednostavljuje dizajn, ali uvodi jednu točku kvara u sustav. Kafka će se srušiti, proces će stati.

Što je API vođen događajima

Dobar odgovor na ovo pitanje nalazi se u izvješću Martina Fowlera (GOTO 2017.) "Mnoga značenja arhitekture vođene događajima".

Ukratko što smo napravili:

  1. Završite sve asinkrone razmjene putem pohrana događaja. Umjesto da svakog zainteresiranog potrošača obavijestimo o promjeni statusa preko mreže, mi događaj o promjeni statusa upišemo u centraliziranu pohranu, a potrošači zainteresirani za tu temu čitaju sve što se odatle pojavi.
  2. Događaj je u ovom slučaju obavijest (Obavijesti) da se negdje nešto promijenilo. Na primjer, promijenio se status narudžbe. Potrošač kojeg zanimaju neki podaci koji prate promjenu statusa, a koji nisu sadržani u obavijesti, može sam saznati njezin status.
  3. Maksimalna opcija je potpuni izvor događaja, prijenos stanja, u kojem događaj sadrži sve podatke potrebne za obradu: odakle je došao iu kojem je statusu došao, kako su se podaci točno promijenili itd. Pitanje je samo izvedivosti i količine informacija koje si možete priuštiti za pohranu.

U sklopu pokretanja alata za povrat novca koristili smo treću opciju. Ova pojednostavljena obrada događaja budući da nije bilo potrebe za izdvajanjem detaljnih informacija, plus eliminirala je scenarij u kojem svaki novi događaj generira niz zahtjeva za dobivanje pojašnjenja od potrošača.

Usluga alata za povrat sredstava nije učitano, pa kod Kafke postoji više okus pera nego potreba. Ne mislim da bi poslovanje bilo sretno kada bi usluga povrata novca postala zahtjevan projekt.

Asinkrona razmjena KAKVA JE

Za asinkrone razmjene PHP odjel obično koristi RabbitMQ. Prikupili smo podatke za zahtjev, stavili ih u red čekanja, a korisnik iste usluge ih je pročitao i poslao (ili nije poslao). Za sam API Lamoda aktivno koristi Swagger. Dizajniramo API, opisujemo ga u Swaggeru i generiramo kod klijenta i poslužitelja. Također koristimo malo poboljšani JSON RPC 2.0.

Na nekim mjestima se koriste ESB sabirnice, neke žive na activeMQ, ali općenito, RabbitMQ - standard.

Asinkrona razmjena BITI

Kod projektiranja razmjene putem sabirnice događaja može se pronaći analogija. Slično opisujemo buduću razmjenu podataka kroz opise strukture događaja. Format yaml, morali smo sami napraviti generiranje koda, generator kreira DTO prema specifikaciji i uči klijente i servere da rade s njima. Generacija ide na dva jezika - golang i php. To pomaže u održavanju dosljednosti knjižnica. Generator je napisan na golangu, zbog čega je i dobio naziv gogi.

Izvor događaja o Kafki je tipična stvar. Postoji rješenje iz glavne poslovne verzije Kafka Confluenta, postoji nakadi, rješenje iz naše domene braće Zalando. Naše motivacija za početak s vanilijevim Kafkom - to znači ostaviti rješenje slobodnim dok konačno ne odlučimo hoćemo li ga koristiti posvuda, a također ostaviti sebi manevarski prostor i poboljšanja: želimo podršku za naše JSON RPC 2.0, generatori za dva jezika i da vidimo što još.

Ironično je da čak ni u tako sretnom slučaju, kada postoji otprilike sličan posao, Zalando, koji je napravio otprilike slično rješenje, ne možemo ga učinkovito koristiti.

Arhitektonski obrazac pri lansiranju je sljedeći: čitamo izravno od Kafke, ali pišemo samo kroz bus događaja. U Kafki je puno toga spremno za čitanje: brokeri, balanseri, a manje-više je spremno za horizontalno skaliranje, to sam htio zadržati. Željeli smo dovršiti snimanje kroz jedan Gateway aka Events-bus, a evo i zašto.

Događaji-bus

Ili autobus za događaje. Ovo je jednostavno http pristupnik bez stanja, koji preuzima nekoliko važnih uloga:

  • Izrada provjere valjanosti — provjeravamo zadovoljavaju li događaji naše specifikacije.
  • Event master sustav, odnosno ovo je glavni i jedini sustav u poduzeću koji odgovara na pitanje koji se događaji s kojim strukturama smatraju važećim. Provjera valjanosti jednostavno uključuje tipove podataka i popise za striktno specificiranje sadržaja.
  • Hash funkcija za sharding - struktura Kafkine poruke je ključ-vrijednost i pomoću raspršivanja ključa izračunava se gdje ga staviti.

Zašto

Radimo u velikoj tvrtki s modernim procesom. Zašto išta mijenjati? Ovo je eksperiment, i očekujemo da ćemo ostvariti nekoliko prednosti.

1:n+1 razmjene (jedan prema više)

Kafka olakšava povezivanje novih korisnika s API-jem.

Recimo da imate imenik koji trebate održavati ažurnim u nekoliko sustava odjednom (iu nekim novim). Prethodno smo izmislili paket koji je implementirao set-API, a glavni sustav je bio obaviješten o adresama potrošača. Sada glavni sustav šalje ažuriranja teme, a svi zainteresirani to čitaju. Pojavio se novi sustav - prijavili smo ga za temu. Da, također paket, ali jednostavniji.

U slučaju alata za povrat sredstava, koji je dio BOB-a, pogodno je da ih sinkroniziramo putem Kafke. Uplata kaže da je novac vraćen: BOB, RT saznali za to, promijenili statuse, Služba za fiskalizaciju saznala za to i izdala ček.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Imamo planove za izradu objedinjene usluge obavijesti koja bi klijenta obavještavala o novostima vezanim uz njegovu narudžbu/povrat. Sada je ta odgovornost raspodijeljena između sustava. Bit će dovoljno da naučimo Notifications Service uhvatiti relevantne informacije od Kafke i odgovoriti na njih (i onemogućiti te obavijesti u drugim sustavima). Neće biti potrebne nove izravne razmjene.

Na temelju podataka

Informacije između sustava postaju transparentne - bez obzira na to kakvo "krvavo poduzeće" imate i bez obzira na to koliki je vaš zaostatak. Lamoda ima odjel za analitiku podataka koji prikuplja podatke iz sustava i stavlja ih u višekratni oblik, kako za poslovne tako i za inteligentne sustave. Kafka vam omogućuje da im brzo date puno podataka i održavate tok informacija ažurnim.

Dnevnik replikacije

Poruke ne nestaju nakon čitanja, kao u RabbitMQ. Kada događaj sadrži dovoljno informacija za obradu, imamo povijest nedavnih promjena na objektu i, po želji, mogućnost primjene tih promjena.

Razdoblje pohranjivanja zapisnika replikacije ovisi o intenzitetu pisanja ove teme; Kafka vam omogućuje fleksibilno postavljanje ograničenja vremena pohranjivanja i količine podataka. Za intenzivne teme važno je da svi potrošači imaju vremena pročitati informaciju prije nego ona nestane, čak i u slučaju kratkotrajne neoperativnosti. Obično je moguće pohraniti podatke za jedinice dana, što je sasvim dovoljno za podršku.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Dalje, malo prepričavanje dokumentacije, za one koji nisu upoznati s Kafkom (slika je također iz dokumentacije)

AMQP ima redove: pišemo poruke u red za korisnika. Tipično, jedan red čekanja obrađuje jedan sustav s istom poslovnom logikom. Ako trebate obavijestiti nekoliko sustava, možete naučiti aplikaciju da piše u nekoliko redova ili konfigurirati razmjenu s fanout mehanizmom, koji ih sam klonira.

Kafka ima sličnu apstrakciju tema, u koji pišete poruke, ali one ne nestaju nakon čitanja. Prema zadanim postavkama, kada se povežete s Kafkom, primate sve poruke i imate mogućnost spremanja tamo gdje ste stali. Odnosno, čitate redom, ne možete označiti poruku kao pročitanu, ali spremiti ID s kojeg možete nastaviti čitati. Id na koji ste se odlučili zove se offset, a mehanizam je commit offset.

Sukladno tome, može se primijeniti drugačija logika. Na primjer, imamo BOB u 4 instance za različite zemlje - Lamoda je u Rusiji, Kazahstanu, Ukrajini, Bjelorusiji. Budući da se postavljaju zasebno, imaju nešto drugačije konfiguracije i vlastitu poslovnu logiku. U poruci navodimo na koju se državu odnosi. Svaki potrošač BOB-a u svakoj zemlji čita s različitim ID-om grupe, a ako se poruka ne odnosi na njih, oni je preskaču, tj. odmah vrši pomak +1. Ako istu temu čita naša Služba za platni promet, onda to čini s posebnom grupom, pa se kompenzacije ne križaju.

Zahtjevi događaja:

  • Potpunost podataka. Volio bih da događaj ima dovoljno podataka da se može obraditi.

  • Integritet. Events-busu delegiramo provjeru je li događaj dosljedan i može li ga obraditi.
  • Redoslijed je važan. U slučaju povratka, prisiljeni smo raditi s poviješću. Kod obavijesti redoslijed nije bitan, ako se radi o homogenim obavijestima e-mail će biti isti bez obzira koja je narudžba stigla prva. U slučaju povrata novca postoji jasan postupak; ako promijenimo redoslijed, pojavit će se iznimke, povrat neće biti kreiran niti obrađen - završit ćemo u drugom statusu.
  • Dosljednost. Imamo trgovinu i sada stvaramo događaje umjesto API-ja. Trebamo način za brz i jeftin prijenos informacija o novim događajima i promjenama postojećih na naše usluge. To se postiže zajedničkom specifikacijom u zasebnom git repozitoriju i generatorima koda. Stoga su klijenti i poslužitelji u različitim uslugama koordinirani.

Kafka u Lamodi

Imamo tri Kafkine instalacije:

  1. trupci;
  2. istraživanje i razvoj;
  3. Događaji-bus.

Danas govorimo samo o posljednjoj točki. Na event-busu nemamo jako velike instalacije - 3 brokera (poslužitelja) i samo 27 tema. U pravilu, jedna tema je jedan proces. Ali ovo je suptilna točka i sada ćemo je dotaknuti.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Iznad je grafikon broja obrtaja u sekundi. Proces povrata je označen tirkiznom linijom (da, onom na X osi), a ružičasta linija je proces ažuriranja sadržaja.

Lamoda katalog sadrži milijune proizvoda, a podaci se stalno ažuriraju. Neke kolekcije izlaze iz mode, nove se izdaju da ih zamijene, au katalogu se stalno pojavljuju novi modeli. Pokušavamo predvidjeti što će našim kupcima biti zanimljivo sutra, stoga stalno kupujemo nove stvari, fotografiramo ih i ažuriramo vitrinu.

Ružičasti vrhovi su ažuriranja proizvoda, odnosno promjene proizvoda. Vidi se da su se dečki slikali, slikali, pa opet! — učitao paket događaja.

Slučajevi korištenja Lamoda Events

Konstruiranu arhitekturu koristimo za sljedeće operacije:

  • Praćenje statusa povrata: poziv na akciju i praćenje statusa iz svih uključenih sustava. Plaćanje, statusi, fiskalizacija, obavijesti. Ovdje smo testirali pristup, napravili alate, prikupili sve bugove, napisali dokumentaciju i rekli kolegama kako to koristiti.
  • Ažuriranje kartica proizvoda: konfiguracija, meta-podaci, karakteristike. Jedan sustav čita (koji prikazuje), a nekoliko ih piše.
  • E-pošta, push i sms: narudžba je preuzeta, narudžba je stigla, povrat je prihvaćen itd., ima ih puno.
  • Zaliha, obnova skladišta — kvantitativno ažuriranje artikala, samo brojevi: dolazak na skladište, povrat. Potrebno je da svi sustavi povezani s rezervacijom robe rade s najaktualnijim podacima. Trenutno je sustav ažuriranja zaliha prilično složen; Kafka će ga pojednostaviti.
  • Analiza podataka (R&D odjel), ML alati, analitika, statistika. Želimo da informacije budu transparentne - Kafka je vrlo pogodan za to.

Sada zanimljiviji dio o velikim neravninama i zanimljivim otkrićima koja su se dogodila u proteklih šest mjeseci.

Problemi dizajna

Recimo da želimo napraviti novu stvar - na primjer, prenijeti cijeli proces isporuke na Kafku. Sada je dio procesa implementiran u Obradu naloga u BOB-u. Postoji statusni model iza prijenosa narudžbe dostavnoj službi, premještanja u međuskladište i tako dalje. Postoji cijeli monolit, čak dva, plus hrpa API-ja posvećenih isporuci. Oni znaju puno više o dostavi.

Čini se da su to slična područja, ali obrada narudžbe u BOB-u i sustav otpreme imaju različite statuse. Na primjer, neke kurirske službe ne šalju međustatuse, već samo konačne: "isporučeno" ili "izgubljeno". Drugi, naprotiv, vrlo detaljno izvještavaju o kretanju robe. Svatko ima svoja pravila provjere valjanosti: za neke je e-pošta važeća, što znači da će biti obrađena; za druge ne vrijedi, ali narudžba će ipak biti obrađena jer postoji telefon za kontakt, a netko će reći da se takva narudžba uopće neće obraditi.

Tok podataka

U slučaju Kafke postavlja se pitanje organizacije protoka podataka. Ovaj zadatak uključuje odabir strategije na temelju nekoliko točaka; prođimo ih sve.

U jednoj temi ili u različitim?

Imamo specifikaciju događaja. U BOB-u pišemo da treba isporučiti tu i takvu narudžbu, te naznačujemo: broj narudžbe, njen sastav, neke SKU-ove i bar kodove itd. Kada roba stigne u skladište, isporuka će moći dobiti statuse, vremenske oznake i sve što je potrebno. Ali tada želimo primati ažuriranja ovih podataka u BOB-u. Imamo obrnuti proces primanja podataka iz dostave. Je li to isti događaj? Ili je ovo posebna razmjena koja zaslužuje svoju temu?

Najvjerojatnije će biti vrlo slični, a iskušenje da se napravi jedna tema nije neutemeljeno, jer zasebna tema znači zasebne potrošače, zasebne konfiguracije, zasebno generiranje svega toga. Ali ne činjenica.

Novo polje ili novi događaj?

Ali ako koristite iste događaje, tada se javlja drugi problem. Na primjer, ne mogu svi sustavi isporuke generirati DTO kakvu može generirati BOB. Šaljemo im ID, ali oni ga ne spremaju jer im ne treba, a sa stajališta pokretanja procesa sabirnice događaja, ovo polje je obavezno.

Ako uvedemo pravilo za sabirnicu događaja da je ovo polje obavezno, tada smo prisiljeni postaviti dodatna pravila provjere valjanosti u BOB-u ili u rukovatelju početnim događajima. Validacija se počinje širiti po cijeloj usluzi - to nije baš zgodno.

Drugi problem je iskušenje za postupnim razvojem. Kažu nam da događaju treba nešto dodati, a možda je to, ako bolje razmislimo, trebao biti poseban događaj. Ali u našoj shemi, zaseban događaj je zasebna tema. Zasebna tema je cijeli proces koji sam gore opisao. Programer je u iskušenju da jednostavno doda još jedno polje u JSON shemu i ponovno ga generira.

U slučaju povrata novca, na događaj smo stigli za pola godine. Imali smo jedan meta-događaj pod nazivom ažuriranje povrata novca, koji je imao polje tipa koje je opisivalo što je to ažuriranje zapravo. Zbog toga smo imali "prekrasne" prekidače s validatorima koji su nam rekli kako potvrditi ovaj događaj ovom vrstom.

Verzija događaja

Za provjeru valjanosti poruka u Kafki možete koristiti Avro, ali je bilo potrebno odmah leći na njega i koristiti Confluent. U našem slučaju, moramo biti oprezni s verzijama. Neće uvijek biti moguće ponovno pročitati poruke iz dnevnika replikacije jer je model "otišao". Uglavnom, ispada da se grade verzije tako da je model kompatibilan unazad: na primjer, polje učinite privremeno neobaveznim. Ako su razlike prevelike, počinjemo pisati u novoj temi, a klijente prebacujemo kada pročitaju staru.

Zajamčen redoslijed čitanja particija

Teme unutar Kafke podijeljene su na particije. Ovo nije jako važno dok dizajniramo entitete i razmjene, ali je važno kada odlučujemo kako to konzumirati i skalirati.

U uobičajenom slučaju, jednu temu pišete u Kafki. Prema zadanim postavkama koristi se jedna particija i sve poruke u ovoj temi idu na nju. A potrošač posljedično čita te poruke uzastopno. Recimo sada trebamo proširiti sustav tako da poruke čitaju dva različita potrošača. Ako, na primjer, šaljete SMS, tada možete reći Kafki da napravi dodatnu particiju i Kafka će početi dijeliti poruke na dva dijela - pola ovdje, pola ovdje.

Kako ih Kafka dijeli? Svaka poruka ima tijelo (u kojem pohranjujemo JSON) i ključ. Ovom ključu možete pridružiti hash funkciju koja će odrediti u koju će particiju poruka ići.

U našem slučaju s povratima, ovo je važno, ako uzmemo dvije particije, tada postoji šansa da će paralelni potrošač obraditi drugi događaj prije prvog i doći će do problema. Funkcija raspršivanja osigurava da poruke s istim ključem završe u istoj particiji.

Događaji vs naredbe

Ovo je još jedan problem s kojim smo se susreli. Događaj je određeni događaj: kažemo da se negdje nešto dogodilo (something_happened), na primjer, neka stavka je otkazana ili je došlo do povrata novca. Ako netko sluša te događaje, tada će se prema "stavka otkazana" kreirati entitet povrata, a "došlo je do povrata" bit će napisano negdje u postavkama.

Ali obično, kada osmišljavate događaje, ne želite ih pisati uzalud - oslanjate se na činjenicu da će ih netko pročitati. Postoji veliko iskušenje da ne napišete nešto_se_dogodilo (artikal_otkazano, povrat_refundiran), nego nešto_treba_učiniti. Na primjer, artikl je spreman za povrat.

S jedne strane, sugerira kako će se događaj koristiti. S druge strane, zvuči mnogo manje kao normalan naziv događaja. Osim toga, nije daleko odavde do naredbe do_something. Ali nemate jamstva da je netko pročitao ovaj događaj; a ako ga čitaš, onda si ga uspješno pročitao; a ako si to uspješno pročitao, onda si nešto napravio, i to nešto je bilo uspješno. U trenutku kada događaj postane učiniti nešto, povratna informacija postaje neophodna, a to je problem.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

U asinkronoj razmjeni u RabbitMQ-u, kada pročitate poruku, odete na http, imate odgovor - barem da je poruka primljena. Kada pišete Kafki, postoji poruka koju ste napisali Kafki, ali ne znate ništa o tome kako je obrađena.

Stoga smo u našem slučaju morali uvesti događaj odgovora i postaviti praćenje tako da ako je poslano toliko događaja, nakon tog i tog vremena treba stići isti broj događaja odgovora. Ako se to ne dogodi, čini se da nešto nije u redu. Na primjer, ako smo poslali događaj "item_ready_to_refund", očekujemo da će se kreirati povrat novca, novac će biti vraćen klijentu, a događaj "money_refunded" će biti poslan nama. Ali to nije sigurno, pa je potrebno praćenje.

nijanse

Postoji prilično očit problem: ako čitate s jedne teme redom, a imate neku lošu poruku, potrošač će pasti, a vi nećete ići dalje. Trebaš zaustaviti sve potrošače, izvrši pomak dalje za nastavak čitanja.

Znali smo za to, računali smo na to, a ipak se dogodilo. A to se dogodilo jer je događaj bio valjan sa stajališta sabirnice događaja, događaj je bio valjan sa gledišta validatora aplikacije, ali nije bio valjan sa gledišta PostgreSQL-a, jer u našem jednom sustavu MySQL s UNSIGNED INT, au novonapisanom je sustav imao PostgreSQL samo s INT. Njegova veličina je malo manja, a Id nije odgovarao. Symfony je umro s iznimkom. Mi smo, naravno, uhvatili iznimku jer smo se oslanjali na nju i namjeravali smo izvršiti ovaj pomak, ali smo prije toga htjeli povećati brojač problema, budući da je poruka neuspješno obrađena. Brojači u ovom projektu također su u bazi podataka, a Symfony je već zatvorio komunikaciju s bazom podataka, a druga je iznimka ubila cijeli proces bez šanse da izvrši offset.

Servis je neko vrijeme ležao - srećom, kod Kafke to nije tako loše, jer poruke ostaju. Kada se rad obnovi, možete ih završiti s čitanjem. Udobno je.

Kafka ima mogućnost postavljanja proizvoljnog pomaka pomoću alata. Ali da biste to učinili, trebate zaustaviti sve potrošače - u našem slučaju pripremite zasebno izdanje u kojem neće biti potrošača, preraspodjele. Zatim u Kafki možete pomaknuti pomak pomoću alata i poruka će proći.

Još jedna nijansa - dnevnik replikacije u odnosu na rdkafka.so - odnosi se na specifičnosti našeg projekta. Koristimo PHP, a u PHP-u u pravilu sve biblioteke komuniciraju s Kafkom preko repozitorija rdkafka.so, a onda postoji nekakav omotač. Možda su to naše osobne poteškoće, ali pokazalo se da nije jednostavno ponovno pročitati dio onoga što smo već pročitali. Općenito, bilo je problema sa softverom.

Vraćajući se na specifičnosti rada s particijama, to je napisano upravo u dokumentaciji potrošači >= particije tema. Ali za ovo sam saznao mnogo kasnije nego što bih želio. Ako želite skalirati i imati dva potrošača, potrebne su vam najmanje dvije particije. Odnosno, ako ste imali jednu particiju u kojoj se nakupilo 20 tisuća poruka, a napravili ste novu, broj poruka se neće skoro izjednačiti. Dakle, da biste imali dva paralelna potrošača, morate se pozabaviti particijama.

nadgledanje

Mislim da će na način na koji to pratimo biti još jasnije koji su problemi u postojećem pristupu.

Na primjer, izračunavamo koliko je proizvoda u bazi nedavno promijenilo svoj status i, sukladno tome, događaji su se trebali dogoditi na temelju tih promjena, te taj broj šaljemo našem sustavu nadzora. Zatim od Kafke dobivamo drugi broj, koliko je zapravo događaja zabilježeno. Očito, razlika između ova dva broja uvijek treba biti nula.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Osim toga, morate pratiti kako radi proizvođač, je li sabirnica događaja primila poruke i kako radi potrošač. Na primjer, u dijagramima ispod, Alat za povrat sredstava dobro radi, ali BOB očito ima nekih problema (plavi vrhovi).

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Već sam spomenuo kašnjenje potrošačke skupine. Grubo rečeno, to je broj nepročitanih poruka. Općenito, naši potrošači rade brzo, tako da je kašnjenje obično 0, ali ponekad može doći do kratkotrajnog vrhunca. Kafka to može učiniti izvan okvira, ali morate postaviti određeni interval.

Postoji projekt jazbinakoji će vam dati više informacija o Kafki. Jednostavno koristi API grupe potrošača kako bi dao status o tome kako grupa radi. Uz OK i Neuspjelo, tu je i upozorenje, a možete saznati da se vaši potrošači ne mogu nositi s tempom proizvodnje - nemaju vremena lektorirati napisano. Sustav je prilično pametan i jednostavan za korištenje.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

Ovako izgleda API odgovor. Ovdje je grupa bob-live-fifa, particija refund.update.v1, status OK, lag 0 - zadnji konačni offset takav i takav.

Iskustvo u razvoju usluge Refund Tool s asinkronim API-jem na Kafki

nadgledanje ažurirano_na SLA (zaglavljeno) Već sam spomenuo. Na primjer, proizvod je promijenjen u status da je spreman za povrat. Instaliramo Cron, koji kaže da ako u roku od 5 minuta ovaj objekt nije otišao na povrat (vrlo brzo vraćamo novac putem sustava plaćanja), onda je nešto definitivno pošlo po zlu, a ovo je definitivno slučaj za podršku. Stoga jednostavno uzmemo Cron koji čita takve stvari i ako su veće od 0 onda šalje upozorenje.

Ukratko, korištenje događaja je zgodno kada:

  • informacije su potrebne za nekoliko sustava;
  • rezultat obrade nije važan;
  • ima malo događaja ili malih događaja.

Čini se da članak ima vrlo specifičnu temu - asinkroni API na Kafki, ali u vezi s njim želio bih preporučiti puno stvari odjednom.
Prvi, sljedeći Visoko opterećenje++ moramo pričekati studeni; u travnju će biti verzija za Sankt Peterburg, au lipnju ćemo govoriti o velikim opterećenjima u Novosibirsku.
Drugo, autor izvješća, Sergei Zaika, član je programskog odbora naše nove konferencije o upravljanju znanjem KnowledgeConf. Konferencija je jednodnevna, održat će se 26. travnja, ali je program vrlo intenzivan.
I bit će u svibnju PHP Rusija и RIT++ (s uključenim DevOpsConfom) - tamo također možete predložiti svoju temu, pričati o svom iskustvu i žaliti se na svoje punjene čunjeve.

Izvor: www.habr.com

Dodajte komentar