Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Šta bi moglo natjerati tako veliku kompaniju kao što je Lamoda, sa pojednostavljenim procesom i desetinama međusobno povezanih usluga, da značajno promijeni svoj pristup? Motivacija može biti potpuno različita: 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 šta tačno možete osvojiti ako implementirate API vođen događajima na Kafki (fewald). Sigurno će biti riječi i o velikim uspjesima i zanimljivim otkrićima – eksperiment ne može bez njih.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Odricanje od odgovornosti: Ovaj članak je zasnovan na materijalima sa sastanka koji je Sergej održao u novembru 2018. na HighLoad++. Lamodino iskustvo uživo u radu sa Kafkom privuklo je slušaoce ništa manje od ostalih izvještaja na rasporedu. Smatramo da je ovo odličan primjer činjenice da uvijek možete i treba pronaći istomišljenike, a organizatori HighLoad++-a će se i dalje truditi da stvore atmosferu pogodnu za to.

O procesu

Lamoda je velika e-commerce platforma koja ima svoj kontakt centar, dostavu (i mnoge podružnice), foto studio, ogromno skladište, a sve to radi na vlastitom softveru. Postoji na desetine načina plaćanja, b2b partnera koji mogu koristiti neke ili sve ove usluge i žele znati najnovije informacije o svojim proizvodima. Osim toga, Lamoda posluje u tri zemlje osim Ruske Federacije i tamo je sve malo drugačije. Ukupno, postoji vjerovatno više od stotinu načina za konfiguraciju nove narudžbe, koja se mora obraditi na svoj način. Sve to funkcionira uz pomoć desetina servisa koji ponekad komuniciraju na neočigledne načine. Postoji i centralni sistem čija su glavna odgovornost statusi naloga. Zovemo je BOB, ja radim s njom.

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

Riječ vođena događajima je prilično zeznuta; malo dalje ćemo detaljnije definirati šta se pod tim podrazumijeva. Počeću od konteksta u kojem smo odlučili da isprobamo API pristup vođen događajima u Kafki.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

U svakoj prodavnici, pored narudžbi koje kupci plaćaju, postoje trenuci kada je trgovina u obavezi da vrati novac jer proizvod nije odgovarao kupcu. Ovo je relativno kratak proces: pojašnjavamo informacije, ako je potrebno, i prenosimo novac.

Ali povratak je postao složeniji zbog promjena u zakonodavstvu i morali smo implementirati zaseban mikroservis za njega.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Naša motivacija:

  1. Zakon FZ-54 - ukratko, zakon nalaže izvještavanje porezne uprave o svakoj novčanoj transakciji, bilo da se radi o povratu ili priznanici, u prilično kratkom SLA-u od nekoliko minuta. Mi, kao kompanija za e-trgovinu, obavljamo dosta poslova. Tehnički, to znači novu odgovornost (a samim tim i novu uslugu) i poboljšanja svih uključenih sistema.
  2. BOB split je interni projekat kompanije kojim se BOB rastereti velikog broja sporednih obaveza i smanjuje njegova ukupna složenost.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Ovaj dijagram prikazuje glavne Lamoda sisteme. Sada ih je većina više konstelacija od 5-10 mikroservisa oko monolita koji se smanjuje. Polako rastu, ali pokušavamo da ih smanjimo, jer je postavljanje fragmenta odabranog u sredini zastrašujuće – ne možemo dozvoliti da padne. Primorani smo rezervirati sve zamjene (strelice) i uzeti u obzir činjenicu da se bilo koja od njih može pokazati nedostupnom.

BOB takođe ima dosta razmena: sisteme plaćanja, sisteme za isporuku, sisteme obaveštenja, itd.

Tehnički BOB je:

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

Uvođenje BOB-a je skupo i bolno, količina koda i problema koje rješava je tolika da niko ne može sve to ubaciti u svoju glavu. Općenito, postoji mnogo razloga da se to pojednostavi.

Proces povratka

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

  • Služba za fiskalizaciju koja će se baviti problemima fiskalizacije i komunikacije sa eksternim službama.
  • Alat za povrat novca, koji jednostavno sadrži nove razmjene kako ne bi naduvao BOB.

Sada proces izgleda ovako:

Iskustvo u razvoju usluge Refund Tool sa asinhronim 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 kaže Plaćanju: "Vrati novac."
  4. Uplata vraća novac.
  5. Refund Tool i BOB međusobno sinhronizuju statuse, jer im je za sada potreban. Još nismo spremni da u potpunosti pređemo na Refund Tool, budući da BOB ima UI, izvještaje za računovodstvo i općenito puno podataka koji se ne mogu tako lako prenijeti. Morate sjediti na dvije stolice.
  6. Zahtjev za fiskalizaciju nestaje.

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

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Prednosti i nedostaci su prilično očigledni. Napravili smo autobus, što znači da sada sve usluge zavise od njega. Ovo pojednostavljuje dizajn, ali uvodi jednu tačku kvara u sistem. Kafka će se srušiti, proces će stati.

Šta je API vođen događajima

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

Ukratko šta smo uradili:

  1. Završi sve asinhrone razmjene putem skladištenje događaja. Umjesto obavještavanja svakog zainteresiranog potrošača o promjeni statusa preko mreže, mi napišemo događaj o promjeni statusa u centraliziranu pohranu, a potrošači zainteresirani za temu čitaju sve što se odatle pojavi.
  2. Događaj u ovom slučaju je obavijest (obavijesti) da se negdje nešto promijenilo. Na primjer, status narudžbe je promijenjen. Potrošač koji je zainteresiran za neke podatke koji prate promjenu statusa koji nisu uključeni u obavijest može sam saznati njen status.
  3. Maksimalna opcija je potpuni izvor događaja, državni transfer, u kojem događaju se nalaze sve informacije potrebne za obradu: odakle su došli i u koji status su otišli, kako su se tačno podaci promijenili itd. Pitanje je samo izvodljivost i količina informacija koju možete sebi priuštiti da pohranite.

Kao dio lansiranja alata za povrat novca, koristili smo treću opciju. Ovo je pojednostavilo obradu događaja jer nije bilo potrebe za izvlačenjem detaljnih informacija, plus je eliminisao scenario u kojem svaki novi događaj generiše nalet pojašnjenih zahteva za dobijanje od potrošača.

Servis alata za povrat novca nije učitano, tako da je Kafka više ukus pera nego potreba. Ne mislim da bi posao bio sretan ako bi usluga povrata novca postala opterećen projekt.

Asinhronizovana razmena KAO JESTE

Za asinhrone razmjene, PHP odjel obično koristi RabbitMQ. Prikupili smo podatke za zahtjev, stavili ga u red čekanja, a korisnik iste usluge ga je pročitao i poslao (ili nije poslao). Za sam API, Lamoda aktivno koristi Swagger. Dizajniramo API, opisujemo ga u Swaggeru i generišemo klijentski i serverski kod. Takođe koristimo malo poboljšani JSON RPC 2.0.

Na nekim mjestima se koriste ESB sabirnice, neke žive na ActiveMQ-u, ali, općenito, RabbitMQ - standardno.

Asinhronizovana razmena TO BE

Prilikom dizajniranja razmjene putem sabirnice događaja može se pratiti analogija. Slično opisujemo buduću razmjenu podataka kroz opise strukture događaja. Yaml format, morali smo sami da uradimo generisanje koda, generator kreira DTO-ove prema specifikaciji i uči klijente i servere da rade sa njima. Generacija ide na dva jezika - golang i php. Ovo pomaže da biblioteke budu dosljedne. Generator je napisan golangom, zbog čega je i dobio ime gogi.

Izvor događaja na 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š motivacija za početak sa vanili Kafka - to znači ostaviti rješenje slobodnim dok konačno ne odlučimo hoćemo li ga koristiti svuda, a isto tako ostaviti sebi prostor za manevar i poboljšanja: želimo podršku za naše JSON RPC 2.0, generatori za dva jezika i da vidimo šta još.

Ironično je da čak i u ovako srećnom slučaju, kada postoji otprilike sličan posao, Zalando, koji je napravio otprilike slično rešenje, ne možemo ga efikasno iskoristiti.

Arhitektonski obrazac pri lansiranju je sljedeći: čitamo direktno iz Kafke, ali pišemo samo preko event-busa. U Kafki ima mnogo toga spremnog za čitanje: brokeri, balanseri, i više-manje je spreman za horizontalno skaliranje, htio sam ovo zadržati. Htjeli smo da završimo snimanje kroz jedan Gateway aka Events-bus, a evo i zašto.

Događaji-bus

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

  • Producing Validation — provjeravamo da li događaji ispunjavaju naše specifikacije.
  • Master sistem događaja, odnosno ovo je glavni i jedini sistem u kompaniji koji odgovara na pitanje koji događaji sa kojim strukturama se smatraju validnim. Validacija jednostavno uključuje tipove podataka i enume za striktno specificiranje sadržaja.
  • Hash funkcija za dijeljenje - struktura Kafka poruke je ključ/vrijednost i pomoću heša ključa se izračunava gdje da se stavi.

Zašto

Radimo u velikoj kompaniji sa pojednostavljenim procesom. Zašto bilo šta mijenjati? Ovo je eksperiment, i očekujemo da ćemo imati nekoliko prednosti.

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

Kafka olakšava povezivanje novih korisnika na API.

Recimo da imate direktorij koji trebate održavati ažurnim u nekoliko sistema odjednom (i u nekim novim). Ranije smo izmislili paket koji je implementirao set-API, a glavni sistem je bio informisan o adresama potrošača. Sada glavni sistem šalje ažuriranja na temu, a svi zainteresovani je čitaju. Pojavio se novi sistem - prijavili smo ga za temu. Da, također u paketu, ali jednostavnije.

U slučaju alata za refundiranje, koji je dio BOB-a, zgodno nam je da ih sinhronizujemo preko Kafke. Uplata kaže da je novac vraćen: BOB, RT su saznali za ovo, promijenili statuse, Služba za fiskalizaciju je to saznala i izdala ček.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Planiramo kreirati jedinstveni servis za obavještavanje koji bi obavještavao klijenta o novostima u vezi s njegovom narudžbom/povratom. Sada je ova odgovornost raspoređena između sistema. Biće nam dovoljno da naučimo servis za obaveštenja da uhvati relevantne informacije od Kafke i odgovori na njih (i onemogući ova obaveštenja u drugim sistemima). Neće biti potrebne nove direktne zamjene.

Na osnovu podataka

Informacije između sistema postaju transparentne – bez obzira na to kakvo “krvavo preduzeće” imate i koliko god da je vaš zaostatak pun. Lamoda ima odjel za analizu podataka koji prikuplja podatke iz sistema i stavlja ih u formu za višekratnu upotrebu, kako za poslovne tako i za inteligentne sisteme. Kafka vam omogućava da im brzo date puno podataka i da taj tok informacija održavate ažurnim.

Dnevnik replikacije

Poruke ne nestaju nakon čitanja, kao u RabbitMQ. Kada događaj sadrži dovoljno informacija za obradu, imamo istoriju nedavnih promena na objektu i, po želji, mogućnost primene ovih promena.

Period skladištenja dnevnika replikacije zavisi od intenziteta pisanja na ovu temu; Kafka vam omogućava da fleksibilno postavite ograničenja za vreme skladištenja i volumen podataka. Za intenzivne teme važno je da svi potrošači imaju vremena da pročitaju informacije prije nego što nestanu, čak i u slučaju kratkotrajne neispravnosti. Obično je moguće pohraniti podatke za jedinice dana, što je sasvim dovoljno za podršku.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

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

AMQP ima redove: mi pišemo poruke u red za potrošača. Tipično, jedan red obrađuje jedan sistem sa istom poslovnom logikom. Ako trebate obavijestiti nekoliko sistema, možete naučiti aplikaciju da piše u nekoliko redova ili konfigurirati razmjenu pomoću mehanizma fanout, koji ih sam klonira.

Kafka ima sličnu apstrakciju tema, u koje pišete poruke, ali one ne nestaju nakon čitanja. Podrazumevano, kada se povežete na Kafku, primate sve poruke i imate opciju da sačuvate tamo gde ste stali. Odnosno, čitate uzastopno, ne možete označiti poruku kao pročitanu, ali sačuvati id iz kojeg možete nastaviti čitati. Id na koji ste se smjestili naziva se offset, a mehanizam je pomak urezivanja.

Shodno tome, može se implementirati drugačija logika. Na primjer, imamo BOB u 4 slučaja za različite zemlje - Lamoda je u Rusiji, Kazahstanu, Ukrajini, Bjelorusiji. Pošto su raspoređeni odvojeno, imaju malo drugačije konfiguracije i vlastitu poslovnu logiku. U poruci navodimo na koju se državu odnosi. Svaki BOB potrošač u svakoj zemlji čita sa različitim ID-om grupe, a ako se poruka ne odnosi na njih, oni je preskaču, tj. odmah urezuje pomak +1. Ako istu temu čita naš servis za platni promet, onda to čini sa posebnom grupom, pa se pomaci ne ukrštaju.

Zahtjevi za događaj:

  • Kompletnost podataka. Želio bih da događaj ima dovoljno podataka da se može obraditi.

  • Integritet Delegiramo Events-busu verifikaciju da je događaj konzistentan i da ga može obraditi.
  • Red je važan. U slučaju povratka, primorani smo da radimo sa istorijom. Kod obavještenja redoslijed nije važan, ako se radi o homogenim obavijestima, email će biti isti bez obzira koja je narudžba prva stigla. U slučaju povraćaja sredstava postoji jasan proces; ako promijenimo narudžbu, pojavit će se izuzeci, povraćaj neće biti kreiran niti obrađen - završit ćemo u drugom statusu.
  • Dosljednost. Imamo prodavnicu i sada kreiramo događaje umjesto API-ja. Potreban nam je način da brzo i jeftino prenesemo informacije o novim događajima i promjenama postojećih na naše usluge. Ovo se postiže zajedničkom specifikacijom u zasebnom git spremištu i generatorima koda. Stoga su klijenti i serveri u različitim servisima koordinirani.

Kafka u Lamodi

Imamo tri Kafka instalacije:

  1. Trupci;
  2. R&D;
  3. Događaji-bus.

Danas govorimo samo o posljednjoj tački. Na event-busu nemamo baš velike instalacije - 3 brokera (servera) i samo 27 tema. Po pravilu, jedna tema je jedan proces. Ali ovo je suptilna tačka i sada ćemo je se dotaknuti.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Iznad je grafikon broja okretaja. Proces povrata novca 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 milione proizvoda, a podaci se stalno ažuriraju. Neke kolekcije izlaze iz mode, izlaze nove koje ih zamjenjuju, a novi modeli se stalno pojavljuju u katalogu. Trudimo se da predvidimo šta će sutra biti interesantno našim kupcima, pa stalno kupujemo nove stvari, fotografišemo ih i ažuriramo vitrinu.

Pink vrhovi su ažuriranja proizvoda, odnosno promjene u proizvodima. Vidi se da su se momci slikali, slikali, pa opet! — učitan paket događaja.

Slučajevi korištenja Lamoda Events

Konstruisanu arhitekturu koristimo za sledeće operacije:

  • Praćenje statusa povratka: poziv na akciju i praćenje statusa iz svih uključenih sistema. Plaćanje, statusi, fiskalizacija, obavještenja. Ovdje smo testirali pristup, napravili alate, prikupili sve greške, napisali dokumentaciju i rekli našim kolegama kako da je koriste.
  • Ažuriranje kartica proizvoda: konfiguracija, meta-podaci, karakteristike. Jedan sistem čita (koji se prikazuje), a nekoliko ih piše.
  • Email, push i sms: narudžba je preuzeta, narudžba je stigla, povraćaj je prihvaćen itd., ima ih puno.
  • Zaliha, obnova magacina — kvantitativno ažuriranje artikala, samo brojevi: dolazak u skladište, povratak. Neophodno je da svi sistemi povezani sa rezervacijom robe rade sa najnovijim podacima. Trenutno je sistem 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 udarcima i zanimljivim otkrićima do kojih je došlo u proteklih šest mjeseci.

Problemi dizajna

Recimo da želimo napraviti novu stvar - na primjer, prebaciti cijeli proces isporuke na Kafku. Sada je dio procesa implementiran u Obradi naloga u BOB-u. Postoji statusni model koji stoji iza prijenosa narudžbe u dostavnu službu, kretanja u međuskladište i tako dalje. Postoji čitav monolit, čak dva, plus gomila API-ja posvećenih isporuci. Oni znaju mnogo više o dostavi.

Čini se da su to slična područja, ali Obrada narudžbi u BOB-u i Sistem 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. Svako ima svoja pravila validacije: za neke je e-pošta važeća, što znači da će biti obrađena; za druge ne važi, ali će narudžba i dalje biti obrađena jer postoji broj telefona za kontakt, a neko će reći da takva narudžba uopće neće biti obrađena.

Tok podataka

U slučaju Kafke postavlja se pitanje organizacije toka podataka. Ovaj zadatak uključuje odabir strategije na osnovu nekoliko tačaka; hajde da ih prođemo kroz sve.

U jednoj temi ili u različitim?

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

Najvjerovatnije će biti vrlo slični, a iskušenje da se napravi jedna tema nije neosnovano, jer posebna tema znači odvojene potrošače, odvojene konfiguracije, odvojenu generaciju svega toga. Ali nije činjenica.

Novo polje ili novi događaj?

Ali ako koristite iste događaje, onda nastaje još jedan problem. Na primjer, ne mogu svi sistemi isporuke generirati vrstu DTO-a koju BOB može generirati. Šaljemo im ID, ali ga oni ne pohranjuju jer im ne treba, a sa stanovišta pokretanja procesa sabirnice događaja ovo polje je obavezno.

Ako uvedemo pravilo za sabirnicu događaja da je ovo polje obavezno, onda smo primorani da postavimo dodatna pravila validacije u BOB-u ili u početnom rukovaocu događaja. Validacija se počinje širiti kroz uslugu - to nije baš zgodno.

Drugi problem je iskušenje inkrementalnog razvoja. Rečeno nam je da događaju treba nešto dodati, a možda je, ako razmislimo, to trebao biti poseban događaj. Ali u našoj shemi, poseban događaj je posebna tema. Posebna tema je cijeli proces koji sam gore opisao. Programer je u iskušenju da jednostavno doda još jedno polje u JSON šemu i ponovo ga generiše.

U slučaju povrata novca, na događaje smo stigli za pola godine. Imali smo jedan meta-događaj pod nazivom ažuriranje povrata novca, koji je imao polje tipa koje opisuje šta je ovo ažuriranje zapravo bilo. Zbog toga smo imali “divne” prekidače sa validatorima koji su nam rekli kako da potvrdimo ovaj događaj sa ovim tipom.

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 ponovo pročitati poruke iz dnevnika replikacije jer je model „otišao“. U osnovi, ispada da se prave verzije tako da je model kompatibilan unatrag: na primjer, učinite polje privremeno opcijskim. Ako su razlike prevelike, počinjemo pisati u novoj temi, a klijente prenosimo kada završe čitanje stare.

Zagarantovan redosled č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 da ga konzumiramo i skaliramo.

U uobičajenom slučaju, jednu temu pišete u Kafki. Po defaultu se koristi jedna particija i sve poruke u ovoj temi idu na nju. I potrošač shodno tome čita ove poruke uzastopno. Recimo da sada moramo proširiti sistem tako da poruke čitaju dva različita potrošača. Ako, na primjer, šaljete SMS, onda možete reći Kafki da napravi dodatnu particiju, a Kafka će početi dijeliti poruke na dva dijela - pola ovdje, pola ovdje.

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

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

Događaji naspram komandi

Ovo je još jedan problem na koji smo naišli. Događaj je određeni događaj: kažemo da se negdje nešto dogodilo (nešto_se dogodilo), na primjer, artikal je otkazan ili je došlo do povrata novca. Ako neko čuje ove događaje, onda će prema “stavka otkazana” biti kreiran entitet za povraćaj, a negdje u postavkama će biti zapisano “povrat novca”.

Ali obično, kada osmišljavate događaje, ne želite da ih pišete uzalud - oslanjate se na činjenicu da će ih neko pročitati. Postoji veliko iskušenje da napišete ne nešto_se dogodilo (stavka_otkazano, refundirano_povratno), već nešto_treba_da se_uradi. Na primjer, predmet je spreman za vraćanje.

S jedne strane, sugerira kako će se događaj koristiti. S druge strane, zvuči mnogo manje kao uobičajeni naziv događaja. Osim toga, nije daleko odavde do naredbe do_something. Ali nemate garanciju da je neko pročitao ovaj događaj; i ako ga pročitate, onda ste ga uspješno pročitali; i ako ste to uspješno pročitali, onda ste nešto uradili i to nešto je bilo uspješno. U trenutku kada neki događaj postane uradi_nešto, povratna informacija postaje neophodna, a to je problem.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

U asinhronoj 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 se pošalje toliko događaja, nakon tog i tog vremena treba stići isti broj događaja odgovora. Ako se to ne dogodi, izgleda da je nešto pošlo po zlu. Na primjer, ako smo poslali događaj “item_ready_to_refund”, očekujemo da će biti kreiran 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čigledan problem: ako čitate iz teme uzastopno, a imate neku lošu poruku, potrošač će pasti, a vi nećete ići dalje. Ti trebas zaustaviti sve potrošače, dodatno pomaknite za nastavak čitanja.

Znali smo za to, računali smo na to, a ipak se dogodilo. I to se desilo jer je događaj bio validan sa stanovišta sabirnice događaja, događaj je bio validan sa stanovišta validatora aplikacije, ali nije bio validan sa stanovišta PostgreSQL-a, jer u našem jednom sistemu MySQL sa UNSIGNED INT, au novonapisanom sistem je imao PostgreSQL samo sa INT. Njegova veličina je malo manja, a Id nije odgovarao. Symfony je umrla sa izuzetkom. Mi smo, naravno, uhvatili izuzetak jer smo se oslanjali na njega, i hteli smo da urezujemo ovaj ofset, ali smo pre toga želeli da povećamo brojač problema, pošto je poruka neuspešno obrađena. Brojači u ovom projektu su takođe u bazi podataka, a Symfony je već zatvorio komunikaciju sa bazom podataka, a drugi izuzetak je ubio ceo proces bez mogućnosti da izvrši ofset.

Servis je zalegao neko vreme - na sreću, kod Kafke to i nije tako loše, jer poruke ostaju. Kada se posao vrati, možete ih završiti sa čitanjem. To je udobno.

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

Još jedna nijansa - dnevnik replikacije vs rdkafka.so - vezano je za specifičnosti našeg projekta. Koristimo PHP, au PHP-u, po pravilu, sve biblioteke komuniciraju sa Kafkom preko rdkafka.so spremišta, a onda postoji neka vrsta omotača. Možda su to naše lične poteškoće, ali pokazalo se da jednostavno ponovno čitanje dijela onoga što smo već pročitali nije tako lako. Općenito, bilo je problema sa softverom.

Vraćajući se na specifičnosti rada sa particijama, to je napisano upravo u dokumentaciji potrošači >= particije tema. Ali saznao sam za ovo mnogo kasnije nego što sam ž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 hiljada poruka, a napravili ste novu, broj poruka se neće uskoro izjednačiti. Stoga, da biste imali dva paralelna potrošača, morate se baviti particijama.

Monitoring

Mislim da će način na koji budemo pratili biti još jasniji koji problemi postoje u postojećem pristupu.

Na primjer, izračunavamo koliko je proizvoda u bazi podataka nedavno promijenilo svoj status i, shodno tome, na osnovu tih promjena su se trebali dogoditi događaji i taj broj šaljemo našem sistemu za praćenje. Zatim od Kafke dobijamo drugi broj, koliko je događaja stvarno zabeleženo. Očigledno, razlika između ova dva broja uvijek bi trebala biti nula.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Osim toga, morate pratiti kako proizvođač radi, da li je sabirnica događaja primila poruke i kako se ponaša potrošač. Na primjer, na grafikonima ispod, Refund Tool radi dobro, ali BOB očigledno ima nekih problema (plavi vrhovi).

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Već sam spomenuo zaostajanje grupe potrošača. Grubo govoreći, ovo je broj nepročitanih poruka. Generalno, 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 projekat Burrowkoji će vam dati više informacija o Kafki. Jednostavno koristi API grupe potrošača da bi dao status kako ova grupa radi. Pored OK i Failed, postoji i upozorenje, a možete saznati da vaši potrošači ne mogu da se izbore sa tempom proizvodnje – nemaju vremena da lektorišu napisano. Sistem je prilično pametan i jednostavan za korištenje.

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

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

Iskustvo u razvoju usluge Refund Tool sa asinhronim API-jem na Kafki

Monitoring updated_at SLA (zaglavio) Već sam pomenuo. Na primjer, proizvod je promijenjen u status da je spreman za vraćanje. Instaliramo Cron koji kaže da ako za 5 minuta ovaj objekat nije otišao na povraćaj (vrlo brzo vraćamo novac preko platnih sistema), onda je nešto definitivno pošlo po zlu i ovo je svakako slučaj za podršku. Stoga jednostavno uzimamo Cron, koji čita takve stvari, a ako su veće od 0, onda šalje upozorenje.

Da rezimiramo, korištenje događaja je zgodno kada:

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

Čini se da članak ima vrlo specifičnu temu - asinhroni API na Kafki, ali u vezi s tim želim preporučiti mnogo stvari odjednom.
Prvo, sledeće HighLoad++ treba sačekati novembar, u aprilu će biti verzija iz Sankt Peterburga, au junu ćemo pričati o velikim opterećenjima u Novosibirsku.
Drugo, autor izvještaja, Sergej Zaika, član je Programskog odbora naše nove konferencije o upravljanju znanjem KnowledgeConf. Konferencija je jednodnevna, održaće se 26. aprila, ali je njen program veoma intenzivan.
I to će biti u maju PHP Rusija и RIT++ (sa uključenim DevOpsConf-om) - 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