Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Kas galėtų priversti tokią didelę bendrovę kaip „Lamoda“, turinčią supaprastintą procesą ir daugybę tarpusavyje susijusių paslaugų, gerokai pakeisti savo požiūrį? Motyvacija gali būti visiškai skirtinga: nuo įstatyminės iki noro eksperimentuoti, būdingo visiems programuotojams.

Tačiau tai nereiškia, kad negalite tikėtis papildomos naudos. Sergejus Zaika jums pasakys, ką tiksliai galite laimėti, jei įdiegsite įvykiais pagrįstą API „Kafka“ (nedaugald). Taip pat tikrai bus kalbama apie didelius kadrus ir įdomius atradimus – be jų eksperimentas neapsieina.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Atsisakymas: šis straipsnis yra pagrįstas medžiaga iš susitikimo, kurį Sergejus surengė 2018 m. lapkritį per HighLoad++. Lamodos gyva darbo su Kafka patirtis pritraukė klausytojų ne mažiau nei kiti pranešimai pagal tvarkaraštį. Manome, kad tai puikus pavyzdys, kad visada galima ir reikia rasti bendraminčių, o HighLoad++ organizatoriai ir toliau stengsis sukurti tam palankią atmosferą.

Apie procesą

Lamoda yra didelė elektroninės prekybos platforma, turinti savo kontaktų centrą, pristatymo paslaugą (ir daug filialų), fotostudiją, didžiulį sandėlį ir visa tai veikia naudojant savo programinę įrangą. Yra daugybė mokėjimo būdų, B2B partnerių, kurie gali naudotis kai kuriomis arba visomis šiomis paslaugomis ir nori sužinoti naujausią informaciją apie savo produktus. Be to, „Lamoda“ veikia trijose šalyse be Rusijos Federacijos ir ten viskas šiek tiek kitaip. Iš viso yra turbūt daugiau nei šimtas būdų, kaip sukonfigūruoti naują užsakymą, kuris turi būti tvarkomas savaip. Visa tai veikia su dešimčių paslaugų, kurios kartais bendrauja neakivaizdžiais būdais, pagalba. Taip pat yra centrinė sistema, kurios pagrindinė atsakomybė yra užsakymų būsenos. Mes ją vadiname BOB, aš su ja dirbu.

Grąžinimo įrankis su įvykiais pagrįsta API

Žodis įvykiai yra gana išgalvotas; šiek tiek toliau mes išsamiau apibūdinsime, ką tai reiškia. Pradėsiu nuo konteksto, kuriame nusprendėme išbandyti įvykiais pagrįstą API metodą Kafkoje.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Bet kurioje parduotuvėje, be užsakymų, už kuriuos klientai moka, pasitaiko atvejų, kai iš parduotuvės reikalaujama grąžinti pinigus, nes prekė klientui netiko. Tai gana trumpas procesas: jei reikia, patiksliname informaciją ir pervedame pinigus.

Tačiau dėl pasikeitusių teisės aktų grąžinimas tapo sudėtingesnis, todėl turėjome įdiegti atskirą mikropaslaugą.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Mūsų motyvacija:

  1. FZ-54 įstatymas - Trumpai tariant, įstatymas reikalauja pranešti mokesčių inspekcijai apie kiekvieną piniginę operaciją, nesvarbu, ar tai būtų grąžinimas, ar kvitas, per gana trumpą, kelių minučių SLA. Mes, kaip elektroninės prekybos įmonė, atliekame gana daug operacijų. Techniškai tai reiškia naują atsakomybę (taigi ir naują paslaugą) ir visų susijusių sistemų patobulinimus.
  2. BOB padalijimas yra įmonės vidinis projektas, skirtas atleisti BOB nuo daugybės nepagrindinių įsipareigojimų ir sumažinti bendrą jo sudėtingumą.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Šioje diagramoje parodytos pagrindinės Lamoda sistemos. Dabar daugumos jų daugiau 5-10 mikroservisų žvaigždynas aplink besitraukiantį monolitą. Jie pamažu auga, bet stengiamės juos mažinti, nes išsiskleisti viduryje pasirinktą fragmentą yra baisu – negalime leisti jam kristi. Esame priversti rezervuoti visas biržas (rodykles) ir atsižvelgti į tai, kad bet kuris iš jų gali pasirodyti nepasiekiamas.

BOB taip pat turi nemažai mainų: mokėjimo sistemos, pristatymo sistemos, pranešimų sistemos ir kt.

Techniškai BOB yra:

  • ~150k kodo eilučių + ~100k eilučių testų;
  • php7.2 + Zend 1 ir Symfony Components 3;
  • >100 API ir ~50 siunčiamų integracijų;
  • 4 šalys su savo verslo logika.

BOB diegimas yra brangus ir skausmingas, kodo ir išsprendžiamų problemų kiekis yra toks, kad niekas negali visko įdėti į galvą. Apskritai, yra daug priežasčių jį supaprastinti.

Grąžinimo procesas

Iš pradžių procese dalyvauja dvi sistemos: BOB ir mokėjimo. Dabar pasirodo dar du:

  • Fiskalizacijos tarnyba, kuri pasirūpins fiskalizacijos ir komunikacijos su išorinėmis tarnybomis problemomis.
  • Grąžinimo įrankis, kuriame tiesiog yra naujų mainų, kad nebūtų išpūstas BOB.

Dabar procesas atrodo taip:

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

  1. BOB gauna prašymą grąžinti pinigus.
  2. BOB kalba apie šį grąžinimo įrankį.
  3. Grąžinimo įrankis mokėjimui sako: „Grąžinkite pinigus“.
  4. Mokėjimas grąžina pinigus.
  5. Grąžinimo įrankis ir BOB sinchronizuoja būsenas tarpusavyje, nes kol kas jiems abiem to reikia. Dar nesame pasiruošę visiškai pereiti prie grąžinimo įrankio, nes BOB turi vartotojo sąsają, ataskaitas apskaitai ir apskritai daug duomenų, kurių negalima taip lengvai perkelti. Turite sėdėti ant dviejų kėdžių.
  6. Prašymas dėl fiskalizacijos išnyksta.

Dėl to Kafkoje padarėme savotišką renginių autobusą – renginį-busą, nuo kurio viskas ir prasidėjo. Hurray, dabar turime vieną nesėkmės tašką (sarkazmą).

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Privalumai ir trūkumai yra gana akivaizdūs. Padarėme autobusą, vadinasi, dabar nuo jo priklauso visos paslaugos. Tai supaprastina dizainą, bet įveda vieną sistemos gedimo tašką. Kafka sugrius, procesas sustos.

Kas yra įvykiais pagrįsta API

Geras atsakymas į šį klausimą yra Martino Fowlerio pranešime (GOTO 2017) „Daugybė įvykių skatinamos architektūros reikšmių“.

Trumpai ką padarėme:

  1. Užbaikite visus asinchroninius mainus per įvykių saugykla. Užuot informavę kiekvieną susidomėjusį vartotoją apie būsenos pasikeitimą tinkle, mes rašome įvykį apie būsenos pasikeitimą į centralizuotą saugyklą, o šia tema besidomintys vartotojai perskaito viską, kas iš ten pasirodo.
  2. Šiuo atveju įvykis yra pranešimas (pranešimai), kad kažkas kažkur pasikeitė. Pavyzdžiui, pasikeitė užsakymo būsena. Vartotojas, besidomintis kai kuriais su būsenos pakeitimu susijusiais duomenimis, kurie nėra įtraukti į pranešimą, gali pats sužinoti jų būseną.
  3. Maksimali galimybė yra visavertis renginių tiekimas, valstybės perdavimas, kuriame įvykyje yra visa informacija, reikalinga apdorojimui: iš kur ji buvo gauta ir į kokią būseną buvo perkelta, kaip tiksliai pasikeitė duomenys ir tt Vienintelis klausimas yra informacijos, kurią galite sau leisti saugoti, pagrįstumas ir kiekis.

Pradėdami grąžinimo įrankį naudojome trečiąją parinktį. Šis supaprastintas įvykių apdorojimas, nes nereikėjo išgauti išsamios informacijos, be to, buvo pašalintas scenarijus, kai kiekvienas naujas įvykis generuoja paaiškinimų gavimo užklausas iš vartotojų.

Grąžinimo įrankių paslauga nepakrautas, todėl Kafka yra daugiau rašiklio skonio nei būtinybė. Nemanau, kad jei pinigų grąžinimo paslauga taptų didelės apkrovos projektu, verslas būtų laimingas.

Asinchroninis keitimas toks, koks yra

Asinchroniniams mainams PHP skyrius dažniausiai naudoja RabbitMQ. Surinkome užklausos duomenis, įdėjome į eilę, o tos pačios paslaugos vartotojas perskaitė ir išsiuntė (arba neišsiuntė). Pačiai API „Lamoda“ aktyviai naudoja „Swagger“. Sukuriame API, aprašome ją Swagger ir generuojame kliento ir serverio kodą. Taip pat naudojame šiek tiek patobulintą JSON RPC 2.0.

Kai kuriose vietose naudojami ESB autobusai, kai kurie veikia su ActiveMQ, tačiau apskritai RabbitMQ – standartinis.

Asinchroninis keitimas TO BE

Projektuojant mainus per renginių autobusą, galima atsekti analogiją. Panašiai aprašome būsimus duomenų mainus per įvykių struktūros aprašymus. Yaml formatas, kodo generavimą turėjome daryti patys, generatorius pagal specifikaciją kuria DTO ir moko klientus bei serverius su jais dirbti. Karta pereina į dvi kalbas - golang ir php. Tai padeda išlaikyti bibliotekų nuoseklumą. Generatorius parašytas golangu, todėl gavo pavadinimą gogi.

Kafkos renginių šaltinis yra tipiškas dalykas. Yra sprendimas iš pagrindinės įmonės „Kafka Confluent“ versijos nakadi, mūsų domeno brolių Zalando sprendimas. Mūsų motyvacija pradėti nuo vanilės Kafka - tai reiškia palikti sprendimą laisvai, kol galiausiai nuspręsime, ar jį naudosime visur, taip pat palikti sau erdvės manevrams ir patobulinimams: norime paramos mūsų JSON RPC 2.0, generatoriai dviem kalboms ir pažiūrėkime, kas dar.

Ironiška, kad net ir tokiu laimingu atveju, kai yra maždaug panašus verslas „Zalando“, kuris padarė maždaug panašų sprendimą, negalime jo efektyviai panaudoti.

Architektūrinis modelis paleidimo metu yra toks: mes skaitome tiesiai iš Kafkos, bet rašome tik per renginius. Kafkoje yra daug paruoštų skaitymui: brokerių, balansuotojų, ir jis daugiau ar mažiau paruoštas horizontaliam mastelio keitimui, norėjau tai išlaikyti. Norėjome užbaigti įrašymą per vieną „Gateway“, dar žinomą kaip „Events-bus“, ir štai kodėl.

Renginiai-autobusas

Arba renginių autobusas. Tai tiesiog be būsenos http šliuzas, kuris atlieka keletą svarbių vaidmenų:

  • Patvirtinimo kūrimas — tikriname, ar renginiai atitinka mūsų specifikacijas.
  • Renginių meistrų sistema, tai yra, tai yra pagrindinė ir vienintelė įmonėje sistema, atsakanti į klausimą, kokie įvykiai su kokiomis struktūromis laikomi galiojančiais. Patvirtinimas tiesiog apima duomenų tipus ir sąrašus, kad būtų griežtai nurodytas turinys.
  • Maišos funkcija suskaidymui - Kafka pranešimo struktūra yra rakto vertė ir naudojant rakto maišą apskaičiuojama, kur jį įdėti.

Kodėl

Dirbame didelėje įmonėje su supaprastintu procesu. Kam ką nors keisti? Tai yra eksperimentas, ir tikimės gauti tam tikros naudos.

1:n+1 mainai (nuo vieno iki daugelio)

„Kafka“ leidžia labai lengvai prijungti naujus vartotojus prie API.

Tarkime, kad turite katalogą, kurį reikia nuolat atnaujinti keliose sistemose vienu metu (ir kai kuriose naujose). Anksčiau mes išradome paketą, kuriame įdiegta set-API, o pagrindinė sistema buvo informuojama apie vartotojų adresus. Dabar pagrindinė sistema siunčia temos atnaujinimus ir visi, kas domisi, ją skaito. Atsirado nauja sistema – užsiregistravome į temą. Taip, irgi ryšulėlis, bet paprasčiau.

Grąžinimo įrankio atveju, kuris yra BOB dalis, mums patogu juos sinchronizuoti per Kafka. Mokėjime rašoma, kad pinigai buvo grąžinti: BOB, RT apie tai sužinojo, pakeitė statusus, Fiskalizacijos tarnyba apie tai sužinojo ir išrašė čekį.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Planuojame sukurti vieningą Pranešimų paslaugą, kuri informuotų klientą apie naujienas apie jo užsakymą/grąžinimus. Dabar ši atsakomybė paskirstyta sistemoms. Mums užteks išmokyti Pranešimų tarnybą pagauti aktualią informaciją iš Kafkos ir į ją atsakyti (ir išjungti šiuos pranešimus kitose sistemose). Naujų tiesioginių mainų nereikės.

Duomenimis pagrįstas

Informacija tarp sistemų tampa skaidri – nesvarbu, kokią „kruviną įmonę“ turite ir koks didelis jūsų atsilikimas. „Lamoda“ turi duomenų analizės skyrių, kuris renka duomenis iš sistemų ir pateikia juos į daugkartinio naudojimo formą tiek verslui, tiek išmaniosioms sistemoms. Kafka leidžia greitai suteikti jiems daug duomenų ir nuolat atnaujinti tą informacijos srautą.

Replikacijos žurnalas

Pranešimai nedingsta po perskaitymo, kaip RabbitMQ. Kai įvykyje yra pakankamai informacijos, kad ją būtų galima apdoroti, turime naujausių objekto pakeitimų istoriją ir, jei norime, galimybę pritaikyti šiuos pakeitimus.

Replikacijos žurnalo saugojimo laikotarpis priklauso nuo rašymo į šią temą intensyvumo; Kafka leidžia lanksčiai nustatyti saugojimo laiko ir duomenų apimties apribojimus. Intensyvioms temoms svarbu, kad visi vartotojai turėtų laiko perskaityti informaciją, kol ji nedingsta, net ir trumpalaikio neveikimo atveju. Paprastai galima saugoti duomenis dienų vienetai, kurio visiškai pakanka paramai.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Toliau šiek tiek dokumentacijos perpasakojimas, tiems, kurie nėra susipažinę su Kafka (nuotrauka taip pat iš dokumentacijos)

AMQP turi eiles: rašome pranešimus į vartotojui skirtą eilę. Paprastai vieną eilę apdoroja viena sistema su ta pačia verslo logika. Jei reikia pranešti kelioms sistemoms, galite išmokyti programą rašyti į kelias eiles arba sukonfigūruoti mainus su fanout mechanizmu, kuris pats jas klonuoja.

Kafka turi panašią abstrakciją tema, kuriame rašote žinutes, bet perskaičius jos nedingsta. Pagal numatytuosius nustatymus, kai prisijungiate prie Kafka, gaunate visus pranešimus ir turite galimybę išsaugoti ten, kur baigėte. Tai reiškia, kad skaitote nuosekliai, galite nežymėti pranešimo kaip skaityto, bet išsaugoti ID, iš kurio galėsite tęsti skaitymą. ID, kurį nustatėte, vadinamas poslinkiu, o mechanizmas yra įsipareigojimo poslinkis.

Atitinkamai galima įgyvendinti skirtingą logiką. Pavyzdžiui, mes turime BOB 4 kartus skirtingose ​​šalyse – Lamoda yra Rusijoje, Kazachstane, Ukrainoje, Baltarusijoje. Kadangi jie diegiami atskirai, jų konfigūracijos ir verslo logika šiek tiek skiriasi. Pranešime nurodome, į kurią šalį kalbama. Kiekvienas BOB vartotojas kiekvienoje šalyje skaito su skirtingu groupId, o jei pranešimas jam netinka, jis jį praleidžia, t.y. iš karto padaro poslinkį +1. Jei tą pačią temą skaito mūsų Mokėjimo tarnyba, tada ji tai daro su atskira grupe, todėl užskaitos nesikerta.

Reikalavimai renginiui:

  • Duomenų išsamumas. Norėčiau, kad renginyje būtų pakankamai duomenų, kad būtų galima jį apdoroti.

  • Vientisumas „Events-bus“ perduodame patvirtinimą, kad įvykis yra nuoseklus ir gali jį apdoroti.
  • Tvarka svarbi. Grąžinimo atveju esame priversti dirbti su istorija. Su pranešimais užsakymas nėra svarbus, jei tai vienarūšiai pranešimai, el. paštas bus vienodas, nepriklausomai nuo to, kuris užsakymas atvyko pirmas. Pinigų grąžinimo atveju yra aiškus procesas, jei pakeisime užsakymą, atsiras išimčių, pinigų grąžinimas nebus sukurtas ar apdorotas – atsidursime kitokioje būsenoje.
  • Nuoseklumas. Turime parduotuvę ir dabar kuriame renginius, o ne API. Mums reikia būdo greitai ir pigiai perduoti informaciją apie naujus įvykius ir esamų pasikeitimus į mūsų paslaugas. Tai pasiekiama naudojant bendrą specifikaciją atskiroje „git“ saugykloje ir kodų generatoriuose. Todėl skirtingų paslaugų klientai ir serveriai yra derinami.

Kafka Lamodoje

Turime tris „Kafka“ įrenginius:

  1. Rąstai;
  2. R&D;
  3. Renginiai-autobusas.

Šiandien mes kalbame tik apie paskutinį dalyką. Renginiuose-buse mes neturime labai didelių instaliacijų - 3 brokeriai (serveriai) ir tik 27 temos. Paprastai viena tema yra vienas procesas. Bet tai yra subtilus dalykas, ir mes jį paliesime dabar.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Viršuje yra rps grafikas. Lėšų grąžinimo procesas pažymėtas turkio spalva (taip, ta, esančia X ašyje), o rožinė linija yra turinio atnaujinimo procesas.

Lamoda kataloge yra milijonai produktų, o duomenys nuolat atnaujinami. Kai kurios kolekcijos išeina iš mados, jas pakeisti išleidžiamos naujos, o kataloge nuolat atsiranda naujų modelių. Stengiamės numatyti, kas rytoj bus įdomu mūsų klientams, todėl nuolat įsigyjame naujų daiktų, juos fotografuojame, atnaujiname vitriną.

Rožinės smailės yra produktų atnaujinimai, tai yra produktų pakeitimai. Matosi, kad vaikinai fotografavosi, fotografavosi, o paskui dar kartą! — prisikrovė renginių paketą.

Lamoda Events naudojimo atvejai

Sukurtą architektūrą naudojame šioms operacijoms:

  • Grąžinimo būsenos stebėjimas: raginimas veikti ir būsenos stebėjimas iš visų susijusių sistemų. Mokėjimas, būsenos, fiskalizavimas, pranešimai. Čia išbandėme metodą, gaminome įrankius, surinkome visas klaidas, rašėme dokumentus ir pasakojome kolegoms, kaip ja naudotis.
  • Produktų kortelių atnaujinimas: konfigūracija, metaduomenys, charakteristikos. Viena sistema skaito (kuri rodoma), o kelios rašo.
  • El. paštu, stumti ir sms: užsakymas atsiimtas, užsakymas atkeliavo, grąžinimas priimtas ir t.t., jų daug.
  • Atsargų, sandėlio atnaujinimas — kiekybinis prekių atnaujinimas, tik skaičiai: atvežimas į sandėlį, grąžinimas. Būtina, kad visos su prekių rezervavimu susijusios sistemos veiktų su naujausiais duomenimis. Šiuo metu atsargų atnaujinimo sistema yra gana sudėtinga, Kafka ją supaprastins.
  • Duomenų analizė (MTEP skyrius), ML įrankiai, analitika, statistika. Norime, kad informacija būtų skaidri – Kafka tam puikiai tinka.

Dabar įdomesnė dalis apie didelius iškilimus ir įdomius atradimus, kurie įvyko per pastaruosius šešis mėnesius.

Dizaino problemos

Tarkime, norime padaryti naują dalyką – pavyzdžiui, perkelti visą pristatymo procesą į „Kafka“. Dabar dalis proceso įdiegta užsakymų apdorojime BOB. Užsakymo perkėlimas į pristatymo tarnybą, perkėlimas į tarpinį sandėlį ir t.t. yra statuso modelis. Yra visas monolitas, net du, plius krūva API, skirtų pristatymui. Jie daug daugiau žino apie pristatymą.

Atrodo, kad tai yra panašios sritys, tačiau užsakymų apdorojimas BOB ir pristatymo sistema turi skirtingas būsenas. Pavyzdžiui, kai kurios kurjerių tarnybos nesiunčia tarpinių būsenų, o tik galutines: „pristatyta“ arba „pamesta“. Kiti, atvirkščiai, labai išsamiai praneša apie prekių judėjimą. Kiekvienas turi savo patvirtinimo taisykles: kai kuriems el. laiškas galioja, vadinasi, bus apdorotas; kitiems jis negalioja, bet uzsakymas vis tiek bus tvarkomas nes yra telefono numeris susisiekimui, ir kas nors pasakys, kad toks uzsakymas isvis nebus vykdomas.

Duomenų srautas

Kafkos atveju iškyla duomenų srauto organizavimo klausimas. Ši užduotis apima strategiją, pagrįstą keliais punktais; apžvelgsime juos visus.

Vienoje temoje ar skirtingose?

Turime renginio specifikaciją. Į BOB rašome, kad reikia pristatyti tokį ir tokį užsakymą, ir nurodome: užsakymo numerį, jo sudėtį, kai kuriuos SKU ir brūkšninius kodus ir kt. Kai prekės atvyks į sandėlį, pristatymas galės gauti būsenas, laiko žymas ir viską, ko reikia. Bet tada norime gauti atnaujinimus apie šiuos BOB duomenis. Mes turime atvirkštinį duomenų gavimo iš pristatymo procesą. Ar tai tas pats įvykis? O gal tai atskiri mainai, kurie nusipelno savo temos?

Greičiausiai jie bus labai panašūs, o pagunda daryti vieną temą nėra be pagrindo, nes atskira tema reiškia atskirus vartotojus, atskiras konfigūracijas, atskirą viso to generaciją. Bet ne faktas.

Nauja sritis ar naujas renginys?

Bet jei naudojate tuos pačius įvykius, iškyla kita problema. Pavyzdžiui, ne visos pristatymo sistemos gali generuoti tokį DTO, kokį gali generuoti BOB. Išsiunčiame jiems ID, bet jie jo neišsaugo, nes jiems jo nereikia, o renginio magistralės proceso pradžios požiūriu šis laukas yra būtinas.

Jei įvesime įvykių magistralės taisyklę, kad šis laukas yra būtinas, BOB arba pradžios įvykių tvarkyklėje būsime priversti nustatyti papildomas patvirtinimo taisykles. Patvirtinimas pradeda plisti visoje paslaugoje – tai nėra labai patogu.

Kita problema yra laipsniško vystymosi pagunda. Mums sako, kad reikia kažką pridėti prie renginio, o gal, jei gerai pagalvotume, tai turėjo būti atskiras renginys. Bet mūsų schemoje atskiras renginys yra atskira tema. Atskira tema yra visas procesas, kurį aprašiau aukščiau. Kūrėjas linkęs tiesiog pridėti kitą lauką prie JSON schemos ir atkurti ją.

Pinigų grąžinimo atveju į renginį atvykome per pusę metų. Turėjome vieną metaįvykį, vadinamą grąžinimo atnaujinimu, kuriame buvo tipo laukas, nurodantis, kas iš tikrųjų buvo šis naujinimas. Dėl šios priežasties mes turėjome „nuostabius“ jungiklius su tikrintojais, kurie mums pasakė, kaip patvirtinti šį įvykį naudojant šį tipą.

Įvykio versijų kūrimas

Norėdami patvirtinti pranešimus Kafka, galite naudoti Avro, bet reikėjo tuoj pat ant jo gultis ir naudoti Confluent. Mūsų atveju turime būti atsargūs su versijomis. Ne visada bus galima perskaityti pranešimus iš replikacijos žurnalo, nes modelis „išėjo“. Iš esmės paaiškėja, kad versijas reikia kurti taip, kad modelis būtų suderinamas atgal: pavyzdžiui, laikinai padarykite lauką neprivalomą. Jei skirtumai per dideli, pradedame rašyti nauja tema, o klientus perkeliame, kai baigia skaityti senąją.

Garantuota skaidinių skaitymo tvarka

Temos Kafkos viduje suskirstytos į pertvaras. Tai nėra labai svarbu, kol mes projektuojame subjektus ir biržas, bet svarbu sprendžiant, kaip jį vartoti ir padidinti.

Įprastu atveju vieną temą rašai Kafka. Pagal numatytuosius nustatymus naudojamas vienas skaidinys, į kurį patenka visi šios temos pranešimai. Todėl vartotojas šiuos pranešimus skaito paeiliui. Tarkime, dabar reikia išplėsti sistemą, kad pranešimus skaitytų du skirtingi vartotojai. Jei, pavyzdžiui, siunčiate SMS, galite pasakyti Kafkai sukurti papildomą skaidinį ir Kafka pradės skaidyti pranešimus į dvi dalis – pusė čia, pusė čia.

Kaip Kafka juos skirsto? Kiekvienas pranešimas turi turinį (kuriame saugome JSON) ir raktą. Prie šio rakto galite pridėti maišos funkciją, kuri nustatys, į kurį skaidinį pateks pranešimas.

Mūsų atveju su pinigų grąžinimu tai svarbu, jei paimsime du skirsnius, tada yra tikimybė, kad paralelinis vartotojas apdoros antrąjį įvykį prieš pirmąjį ir bus problemų. Maišos funkcija užtikrina, kad pranešimai su tuo pačiu raktu atsidurtų tame pačiame skaidinyje.

Įvykiai vs komandos

Tai dar viena problema, su kuria susidūrėme. Įvykis yra tam tikras įvykis: sakome, kad kažkur kažkas atsitiko (kažkas_atsitiko), pavyzdžiui, prekė buvo atšaukta arba buvo grąžinti pinigai. Jei kas nors klausosi šių įvykių, pagal „prekė atšaukta“ bus sukurtas pinigų grąžinimo objektas, o „grąžinimas įvyko“ kažkur nustatymuose.

Tačiau paprastai kurdami renginius nenorite jų rašyti veltui – pasikliaujate tuo, kad kažkas juos perskaitys. Kyla didelė pagunda rašyti ne kas nors_įvyko (prekė_atšaukta, grąžinta_grąžinta), o kažkas_turėtų_būti_padaryta. Pavyzdžiui, prekė paruošta grąžinti.

Viena vertus, tai rodo, kaip renginys bus naudojamas. Kita vertus, tai daug mažiau skamba kaip įprastas įvykio pavadinimas. Be to, netoli nuo čia iki komandos do_something. Bet jūs neturite garantijų, kad kas nors perskaitė šį įvykį; o jei perskaitei, vadinasi, sėkmingai perskaitei; o jei sėkmingai perskaitei, vadinasi, kažką padarei, ir tas kažkas pavyko. Kai įvykis tampa ką nors padaryti, grįžtamasis ryšys tampa būtinas, ir tai yra problema.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Asinchroninio apsikeitimo metu RabbitMQ, kai skaitote pranešimą, eikite į http, gausite atsakymą – bent jau kad pranešimas gautas. Kai rašai Kafkai, pasirodo žinutė, kurią parašei Kafkai, bet nieko nežinai, kaip ji buvo apdorota.

Todėl mūsų atveju turėjome įvesti atsako įvykį ir nustatyti stebėjimą, kad jei būtų išsiųsta tiek įvykių, po tokio ir tokio laiko atkeliautų tiek pat atsakymo įvykių. Jei taip neatsitiks, atrodo, kad kažkas ne taip. Pavyzdžiui, jei išsiuntėme įvykį „item_ready_to_refund“, tikimės, kad bus sukurtas pinigų grąžinimas, pinigai bus grąžinti klientui, o įvykis „money_refunded“ bus išsiųstas mums. Tačiau tai nėra tikra, todėl reikia stebėti.

Niuansai

Yra gana akivaizdi problema: jei skaitote iš temos nuosekliai ir turite kokią nors blogą žinutę, vartotojas nukris, o jūs toliau nenueisite. Tau reikia sustabdyti visus vartotojus, toliau atlikite poslinkį, kad tęstumėte skaitymą.

Mes apie tai žinojome, tikėjomės, bet taip atsitiko. Ir taip atsitiko todėl, kad įvykis galiojo įvykių magistralės požiūriu, įvykis galiojo programos tikrintuvo požiūriu, bet negaliojo PostgreSQL požiūriu, nes mūsų vienoje sistemoje MySQL su UNSIGNED INT, o naujai parašytoje sistemoje buvo PostgreSQL tik su INT. Jo dydis yra šiek tiek mažesnis, o ID netiko. Symfony mirė su išimtimi. Žinoma, mes pastebėjome išimtį, nes ja pasitikėjome ir ketinome atlikti šį kompensavimą, bet prieš tai norėjome padidinti problemų skaitiklį, nes pranešimas buvo apdorotas nesėkmingai. Šio projekto skaitikliai taip pat yra duomenų bazėje, o „Symfony“ jau uždarė ryšį su duomenų baze, o antroji išimtis nužudė visą procesą be galimybės atlikti kompensaciją.

Tarnyba kurį laiką gulėjo - laimei, su Kafka tai nėra taip blogai, nes žinutės išlieka. Kai darbas bus atkurtas, galite baigti juos skaityti. Tai patogu.

Kafka turi galimybę nustatyti savavališką poslinkį naudodama įrankius. Tačiau norėdami tai padaryti, turite sustabdyti visus vartotojus - mūsų atveju paruoškite atskirą leidimą, kuriame nebus vartotojų, perskirstymų. Tada Kafkoje galite perkelti poslinkį naudodami įrankius, ir pranešimas bus išsiųstas.

Kitas niuansas - replikacijos žurnalas vs rdkafka.so – yra susijęs su mūsų projekto specifika. Mes naudojame PHP, o PHP, kaip taisyklė, visos bibliotekos bendrauja su Kafka per rdkafka.so saugyklą, o tada yra kažkoks paketas. Galbūt tai mūsų asmeniniai sunkumai, bet pasirodė, kad paprasčiausiai perskaityti gabalėlį to, ką jau buvome perskaitę, nėra taip paprasta. Apskritai buvo programinės įrangos problemų.

Grįžtant prie darbo su pertvaromis specifikos, tai parašyta tiesiai dokumentacijoje vartotojai >= temų skirsniai. Tačiau apie tai sužinojau daug vėliau, nei būčiau norėjęs. Jei norite padidinti mastelį ir turėti du vartotojus, jums reikia bent dviejų skaidinių. Tai yra, jei turėjote vieną skaidinį, kuriame buvo sukaupta 20 tūkstančių pranešimų, ir padarėte naują, pranešimų skaičius greitai nebus išlygintas. Todėl norint turėti du lygiagrečius vartotojus, reikia susitvarkyti su pertvaromis.

Stebėjimas

Manau, kad tai, kaip mes tai stebėsime, bus dar aiškiau, kokios problemos yra esamame požiūryje.

Pavyzdžiui, apskaičiuojame, kiek duomenų bazėje esančių produktų pastaruoju metu pakeitė savo būseną ir atitinkamai pagal šiuos pakeitimus turėjo įvykti įvykiai, ir šį skaičių siunčiame į savo stebėjimo sistemą. Tada iš Kafkos gauname antrą skaičių, kiek įvykių iš tikrųjų buvo užfiksuota. Akivaizdu, kad skirtumas tarp šių dviejų skaičių visada turėtų būti lygus nuliui.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Be to, reikia stebėti, kaip sekasi gamintojui, ar įvykiai-bus gautos žinutės ir kaip sekasi vartotojui. Pavyzdžiui, toliau pateiktose diagramose „Refund Tool“ veikia gerai, tačiau BOB akivaizdžiai turi tam tikrų problemų (mėlynos smailės).

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Jau minėjau vartotojų grupės atsilikimą. Grubiai tariant, tai yra neskaitytų pranešimų skaičius. Apskritai mūsų vartotojai dirba greitai, todėl atsilikimas dažniausiai būna 0, tačiau kartais gali būti ir trumpalaikis pikas. Kafka gali tai padaryti iš dėžutės, tačiau jums reikia nustatyti tam tikrą intervalą.

Yra projektas Burzaskuri suteiks daugiau informacijos apie Kafką. Ji tiesiog naudoja vartotojų grupės API, kad pateiktų būseną, kaip sekasi šiai grupei. Be Gerai ir Nepavyko, yra įspėjimas, ir jūs galite sužinoti, kad jūsų vartotojai negali susidoroti su gamybos tempu - jie neturi laiko korektūros perskaityti, kas parašyta. Sistema yra gana protinga ir paprasta naudoti.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Taip atrodo API atsakymas. Čia yra grupė bob-live-fifa, skaidinys refund.update.v1, būsena OK, lag 0 - paskutinis galutinis poslinkis toks ir toks.

Patirtis kuriant grąžinimo įrankio paslaugą su asinchronine API sistemoje Kafka

Stebėjimas updated_at SLA (užstrigo) jau minėjau. Pavyzdžiui, prekės būsena pasikeitė į paruoštą grąžinti. Įdiegiame Cron, kuris sako, kad jei per 5 minutes šis objektas nenuėjo grąžinti (labai greitai grąžiname pinigus per mokėjimo sistemas), tai tikrai kažkas nutiko, ir tai tikrai palaikymo atvejis. Todėl mes tiesiog paimame Cron, kuris skaito tokius dalykus, ir jei jie yra didesni nei 0, tada jis siunčia įspėjimą.

Apibendrinant galima pasakyti, kad renginių naudojimas yra patogus, kai:

  • informacija reikalinga kelioms sistemoms;
  • apdorojimo rezultatas nėra svarbus;
  • yra mažai įvykių arba nedidelių įvykių.

Atrodytų, kad straipsnyje yra labai specifinė tema - asinchroninė API Kafka, tačiau dėl to norėčiau rekomenduoti daug dalykų vienu metu.
Pirma, toliau HighLoad++ reikia palaukti iki lapkričio, balandį bus Sankt Peterburgo versija, o birželį kalbėsime apie dideles apkrovas Novosibirske.
Antra, pranešimo autorius Sergejus Zaika yra mūsų naujos žinių valdymo konferencijos programos komiteto narys. KnowledgeConf. Konferencija yra vienadienė, vyks balandžio 26 d., tačiau jos programa labai intensyvi.
Ir tai bus gegužės mėnesį PHP Rusija и RIT++ (su DevOpsConf) – ten taip pat galite pasiūlyti savo temą, pasikalbėti apie savo patirtį ir skųstis dėl savo prikimštų kūgių.

Šaltinis: www.habr.com

Добавить комментарий