Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Wat koe sa'n grut bedriuw as Lamoda twinge, mei in streamlined proses en tsientallen meiinoar ferbûne tsjinsten, om syn oanpak signifikant te feroarjen? Motivaasje kin folslein oars wêze: fan wetjouwende oant de winsk om te eksperimintearjen dy't inherent is oan alle programmeurs.

Mar dit betsjut net dat jo net kinne rekkenje op ekstra foardielen. Sergey Zaika sil jo fertelle wat jo krekt kinne winne as jo de eveneminten-oandreaune API op Kafka ymplementearje (pearald). Der sil grif ek praat wurde oer grutte shots en nijsgjirrige ûntdekkingen - it eksperimint kin net sûnder.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Disclaimer: Dit artikel is basearre op materialen fan in gearkomste dy't Sergey yn novimber 2018 hold op HighLoad ++. Lamoda's live ûnderfining fan wurkjen mei Kafka luts harkers net minder dan oare rapporten op it skema. Wy tinke dat dit in treflik foarbyld is fan it feit dat jo like-minded minsken kinne en moatte altyd fine, en de organisatoaren fan HighLoad++ sille fierder besykje te meitsjen in sfear dy't befoarderlik foar dit.

Oer it proses

Lamoda is in grut e-commerce platfoarm dat in eigen kontaktsintrum hat, leveringstsjinst (en in protte filialen), in fotostudio, in enoarm pakhús, en dit alles rint op har eigen software. D'r binne tsientallen betelmethoden, b2b-partners dy't guon of al dizze tsjinsten kinne brûke en aktuele ynformaasje wolle witte oer har produkten. Derneist wurket Lamoda yn trije lannen neist de Russyske Federaasje en dêr is alles wat oars. Yn totaal binne d'r wierskynlik mear as hûndert manieren om in nije oarder te konfigurearjen, dy't op syn eigen manier ferwurke wurde moat. Dit alles wurket mei help fan tsientallen tsjinsten dy't soms kommunisearje op net-foar de hân lizzende manieren. D'r is ek in sintraal systeem wêrfan de haadferantwurdlikens oarderstatus is. Wy neame har BOB, ik wurkje mei har.

Refund Tool mei eveneminten-oandreaune API

It wurd foarfallen-oandreaune is nochal hackneyed; In bytsje fierder sille wy yn mear detail bepale wat hjirmei bedoeld wurdt. Ik sil begjinne mei de kontekst wêryn't wy besletten hawwe om de eveneminten-oandreaune API-oanpak yn Kafka te besykjen.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Yn elke winkel, neist bestellingen wêrfoar klanten betelje, binne d'r tiden dat de winkel ferplicht is om jild werom te jaan, om't it produkt net by de klant paste. Dit is in relatyf koart proses: wy ferdúdlikje de ynformaasje, as it nedich is, en drage it jild oer.

Mar it weromkommen waard komplisearre troch feroaringen yn wetjouwing, en wy moasten der in aparte mikrotsjinst foar útfiere.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Us motivaasje:

  1. Wet FZ-54 - koartsein, de wet fereasket rapportaazje oan it belestingkantoar oer elke monetêre transaksje, of it no in rendemint of in ûntfangst is, binnen in frij koarte SLA fan in pear minuten. Wy, as e-commerce bedriuw, fiere in protte operaasjes út. Technysk betsjut dit nije ferantwurdlikens (en dus in nije tsjinst) en ferbetteringen yn alle belutsen systemen.
  2. BOB split is in ynterne projekt fan it bedriuw om BOB te ûntlêsten fan in grut oantal net-kearnferantwurdlikheden en syn totale kompleksiteit te ferminderjen.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Dit diagram lit de wichtichste Lamoda-systemen sjen. No binne de measten mear in konstellaasje fan 5-10 microservices om in krimp monolith. Se groeie stadichoan, mar wy besykje se lytser te meitsjen, om't it ynsetten fan it yn 'e midden selektearre fragmint eng is - wy kinne it net litte falle. Wy binne twongen om alle útwikselingen (pylken) te reservearjen en rekken te hâlden mei it feit dat ien fan har kin blike te wêzen net beskikber.

BOB hat ek nochal in soad útwikselings: betellingssystemen, leveringssystemen, notifikaasjesystemen, ensfh.

Technysk BOB is:

  • ~150k rigels fan koade + ~100k rigels fan tests;
  • php7.2 + Zend 1 & Symfony Components 3;
  • >100 API's & ~50 útgeande yntegraasjes;
  • 4 lannen mei har eigen saaklike logika.

It ynsetten fan BOB is djoer en pynlik, de hoemannichte koade en problemen dy't it oplost is sa dat gjinien it allegear yn 'e holle kin sette. Yn 't algemien binne d'r in protte redenen om it te ferienfâldigjen.

Return Process

Yn it earstoan binne twa systemen belutsen by it proses: BOB en betelling. No ferskine noch twa:

  • Fiskalisaasjetsjinst, dy't problemen sil soargje foar fiskalisaasje en kommunikaasje mei eksterne tsjinsten.
  • Refund Tool, dat gewoan nije útwikselingen befettet om de BOB net op te blazen.

No sjocht it proses der sa út:

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

  1. BOB krijt in fersyk om weromjefte.
  2. BOB praat oer dit Refund Tool.
  3. It werombetelle-ark fertelt Betelling: "Jild weromjaan."
  4. Betelling jout it jild werom.
  5. Refund Tool en BOB syngronisearje statusen mei elkoar, om't se it no beide nedich hawwe. Wy binne noch net ree om folslein oer te skeakeljen nei it Refund Tool, om't BOB in UI hat, rapporten foar boekhâlding, en yn 't algemien in protte gegevens dy't net sa maklik kinne wurde oerdroegen. Jo moatte op twa stuollen sitte.
  6. It fersyk om fiskalisaasje giet fuort.

As gefolch hawwe wy op Kafka in soarte fan evenemintebus makke - event-bus, dêr't alles op begon. Hoera, no hawwe wy ien punt fan mislearring (sarkasme).

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

De foar- en neidielen binne frij dúdlik. We makken in bus, dat betsjut dat no alle tsjinsten der fan ôfhingje. Dit simplifies it ûntwerp, mar yntrodusearret ien punt fan mislearring yn it systeem. Kafka sil crashe, it proses sil stopje.

Wat is in eveneminten-oandreaune API

In goed antwurd op dizze fraach is yn it rapport fan Martin Fowler (GOTO 2017) "De protte betsjuttingen fan evenemint-oandreaune arsjitektuer".

Koartsein wat wy dien hawwe:

  1. Wrap up alle asynchrone útwikselings fia events opslach. Yn stee fan in ynformearje alle ynteressearre konsumint oer in status feroaring oer it netwurk, wy skriuwe in evenemint oer in status feroaring oan in sintrale opslach, en konsuminten ynteressearre yn it ûnderwerp lêzen alles dat ferskynt út dêr.
  2. It barren yn dit gefal is in notifikaasje (Notifikaasjes) dat der earne wat feroare is. Bygelyks, de bestelling status is feroare. In konsumint dy't ynteressearre is yn guon gegevens dy't de statusferoaring begeliede dy't net yn 'e notifikaasje binne opnommen, kin har status sels fine.
  3. De maksimale opsje is folweardige evenemint sourcing, steat oerdracht, yn hokker gefal befettet alle ynformaasje dy't nedich is foar ferwurking: wêr't it wei kaam en hokker status it gie, hoe krekt de gegevens binne feroare, ensfh. De iennichste fraach is de helberens en de hoemannichte ynformaasje dy't jo betelje kinne om te bewarjen.

As ûnderdiel fan 'e lansearring fan it Refund Tool hawwe wy de tredde opsje brûkt. Dizze ferienfâldige ferwurking fan eveneminten, om't d'r gjin need wie om detaillearre ynformaasje te ekstrahearjen, en it elimineare it senario wêr't elk nij evenemint in burst genereart fan ferdúdlikjende oanfragen fan konsuminten.

Refund Tool Service net laden, sa Kafka is der mear in smaak fan 'e pinne as in needsaak. Ik tink net dat as de restitúsjetsjinst in projekt mei hege lading waard, it bedriuw bliid wêze soe.

Async útwikseling AS IS

Foar asynchrone útwikselingen brûkt de PHP-ôfdieling gewoanlik RabbitMQ. Wy sammele de gegevens foar it fersyk, sette it yn in wachtrige, en de konsumint fan deselde tsjinst lies it en stjoerde it (of stjoerde it net). Foar de API sels brûkt Lamoda Swagger aktyf. Wy ûntwerpe in API, beskriuwe it yn Swagger, en generearje client- en serverkoade. Wy brûke ek in wat ferbettere JSON RPC 2.0.

Op guon plakken wurde ESB-bussen brûkt, guon libje op activeMQ, mar yn 't algemien, RabbitMQ - standert.

Async útwikseling TO BE

By it ûntwerpen fan útwikseling fia eveneminten-bus, kin in analogy wurde opspoard. Wy beskriuwe op deselde manier takomstige gegevensútwikseling fia beskriuwings fan evenemintestruktuer. It yaml-formaat, wy moasten sels de koade generearje, de generator makket DTO's neffens de spesifikaasje en leart kliïnten en servers om mei har te wurkjen. Generaasje giet yn twa talen - golang en php. Dit helpt biblioteken konsekwint te hâlden. De generator is skreaun yn golang, en dêrom krige it de namme gogi.

Event-sourcing op Kafka is in typysk ding. D'r is in oplossing fan 'e haadbedriuwferzje fan Kafka Confluent, d'r is nakadi, in oplossing fan ús domeinbruorren Zalando. Ús motivaasje om te begjinnen mei vanille Kafka - dit betsjut dat wy de oplossing frij litte oant wy úteinlik beslute oft wy it oeral brûke sille, en ússels ek romte litte foar manoeuvre en ferbetteringen: wy wolle stipe foar ús JSON RPC 2.0, generators foar twa talen en lit ús sjen wat oars.

It is ironysk dat sels yn sa'n lokkich gefal, as d'r in sawat ferlykber bedriuw is, Zalando, dy't in sawat ferlykbere oplossing makke, wy it net effektyf brûke kinne.

De arsjitektoanyske patroan by lansearring is as folget: wy lêze direkt út Kafka, mar skriuwe allinnich fia eveneminten-bus. Der is in protte klear foar lêzen yn Kafka: makelders, balancers, en it is min of mear klear foar horizontale skaalfergrutting, ik woe dit hâlde. Wy woenen de opname foltôgje fia ien Gateway aka Events-bus, en hjir is wêrom.

Eveneminten-bus

Of in evenemintebus. Dit is gewoan in steatleaze http-gateway, dy't ferskate wichtige rollen oannimt:

  • Produsearje Validaasje - wy kontrolearje dat de eveneminten foldogge oan ús spesifikaasjes.
  • Event master systeem, dat is, dit is it wichtichste en ienige systeem yn it bedriuw dat de fraach beantwurdet fan hokker eveneminten mei hokker struktueren jildich wurde beskôge. Validaasje omfettet gewoan gegevenstypen en enums om ynhâld strikt oan te jaan.
  • Hash funksje foar sharding - de Kafka-berjochtstruktuer is kaai-wearde en mei help fan de hash fan kaai wurdt berekkene wêr't it moat pleatse.

Wêrom

Wy wurkje yn in grut bedriuw mei in streamlined proses. Wêrom wat feroarje? Dit is in eksperimint, en wy ferwachtsje in rispinge ferskate foardielen.

1:n+1 útwikselingen (ien nei folle)

Kafka makket it heul maklik om nije konsuminten te ferbinen mei de API.

Litte wy sizze dat jo in map hawwe dy't jo moatte bywurkje yn ferskate systemen tagelyk (en yn guon nije). Earder hawwe wy in bondel útfûn dy't set-API ymplementearre, en it mastersysteem waard ynformearre oer konsumintadressen. No stjoert it mastersysteem updates nei it ûnderwerp, en elkenien dy't ynteressearre is lêst it. In nij systeem is ferskynd - wy hawwe it oanmeld foar it ûnderwerp. Ja, ek bondel, mar ienfâldiger.

Yn it gefal fan restitúsje-ark, dat in stik BOB is, is it handich foar ús om se syngronisearre te hâlden fia Kafka. Betelling seit dat it jild waard werom: BOB, RT fûn út oer dit, feroare harren statuses, Fiscalization Service fûn út oer dit en útjûn in sjek.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Wy hawwe plannen om in unifoarme notifikaasjetsjinst te meitsjen dy't de klant soe ynformearje oer nijs oangeande syn bestelling / rendemint. No is dizze ferantwurdlikens ferspraat tusken systemen. It sil genôch wêze foar ús om de Notifikaasjetsjinst te learen om relevante ynformaasje fan Kafka te fangen en derop te reagearjen (en dizze notifikaasjes yn oare systemen útskeakelje). Gjin nije direkte útwikselingen sille nedich wêze.

Datastjoerd

Ynformaasje tusken systemen wurdt transparant - nettsjinsteande hokker "bloedige ûndernimming" jo hawwe en hoe plomp jo efterstân ek is. Lamoda hat in ôfdieling Data Analytics dy't gegevens sammelt fan systemen en set it yn in werbrûkbere foarm, sawol foar bedriuw as foar yntelliginte systemen. Kafka lit jo har fluch in protte gegevens jaan en dizze ynformaasjestream bywurke hâlde.

Replikaasje log

Berjochten ferdwine net nei it lêzen, lykas yn RabbitMQ. As in evenemint befettet genôch ynformaasje foar ferwurking, wy hawwe in skiednis fan resinte feroarings oan it objekt, en, as winske, de mooglikheid om te passen dizze feroarings.

De opslachperioade fan it replikaasjelogboek hinget ôf fan 'e yntensiteit fan skriuwen nei dit ûnderwerp; Kafka lit jo fleksibel limiten ynstelle op opslachtiid en gegevensvolumint. Foar yntinsive ûnderwerpen is it wichtich dat alle konsuminten tiid hawwe om de ynformaasje te lêzen foardat it ferdwynt, sels yn it gefal fan koarte termyn inoperabiliteit. It is meastal mooglik om te bewarjen gegevens foar ienheden fan dagen, dat is genôch foar stipe.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Folgjende, in bytsje wertelling fan 'e dokumintaasje, foar dyjingen dy't net bekend binne mei Kafka (de foto is ek út' e dokumintaasje)

AMQP hat wachtrijen: wy skriuwe berjochten nei in wachtrige foar de konsumint. Typysk wurdt ien wachtrige ferwurke troch ien systeem mei deselde saaklike logika. As jo ​​ferskate systemen moatte notify, kinne jo de applikaasje leare om te skriuwen nei ferskate wachtrigen of konfigurearje útwikseling mei de fanout-meganisme, dy't se sels klonet.

Kafka hat in ferlykbere abstraksje ûnderwerp, wêryn jo berjochten skriuwe, mar se ferdwine net nei it lêzen. Standert, as jo ferbine mei Kafka, ûntfange jo alle berjochten en hawwe jo de opsje om te bewarjen wêr't jo ophâlde. Dat is, jo lêze sequentially, jo meie it berjocht net as lêzen markearje, mar bewarje de id wêrfan jo dan fierder kinne lêze. De Id dy't jo fêstige op hjit offset, en it meganisme is commit offset.

Dêrtroch kinne ferskate logika wurde ymplementearre. Wy hawwe bygelyks BOB yn 4 gefallen foar ferskate lannen - Lamoda is yn Ruslân, Kazachstan, Oekraïne, Wyt-Ruslân. Om't se apart wurde ynset, hawwe se wat ferskillende konfiguraasjes en har eigen bedriuwslogika. Wy jouwe yn it berjocht oan op hokker lân it giet. Elke BOB-konsumint yn elk lân lêst mei in oare groupId, en as it berjocht net op har jildt, slaan se it oer, d.w.s. commits fuortendaliks offset +1. As itselde ûnderwerp wurdt lêzen troch ús betellingstsjinst, dan docht it dat mei in aparte groep, en dêrom krúst offsets net.

Event easken:

  • Gegevens folsleinens. Ik wol graach dat it evenemint genôch gegevens hat sadat it ferwurke wurde kin.

  • Yntegriteit. Wy delegearje oan Events-bus de ferifikaasje dat it evenemint konsekwint is en it kin ferwurkje.
  • De folchoarder is wichtich. Yn it gefal fan in weromkear binne wy ​​twongen om te wurkjen mei skiednis. Mei notifikaasjes is de bestelling net wichtich, as it homogene notifikaasjes binne, sil de e-post itselde wêze, nettsjinsteande hokker bestelling earst kaam. Yn it gefal fan in weromjefte is d'r in dúdlik proses; as wy de oarder feroarje, sille útsûnderings ûntstean, de restitúsje sil net oanmakke of ferwurke wurde - wy sille einigje yn in oare status.
  • Konsistinsje. Wy hawwe in winkel, en no meitsje wy eveneminten ynstee fan in API. Wy hawwe in manier nedich om fluch en goedkeap ynformaasje oer nije eveneminten en feroarings oan besteande nei ús tsjinsten te stjoeren. Dit wurdt berikt troch in mienskiplike spesifikaasje yn in aparte git-repository en koade-generators. Dêrom wurde kliïnten en servers yn ferskate tsjinsten koördinearre.

Kafka yn Lamoda

Wy hawwe trije Kafka-ynstallaasjes:

  1. logs;
  2. R&D;
  3. Eveneminten-bus.

Hjoed prate wy allinich oer it lêste punt. By eveneminten-bus hawwe wy net heul grutte ynstallaasjes - 3 makelders (tsjinners) en allinich 27 ûnderwerpen. As regel is ien ûnderwerp ien proses. Mar dit is in subtyl punt, en wy sille it no oanrekke.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Hjirboppe is de rps-grafyk. It fergoedingsproses is markearre mei in turquoise line (ja, dy op 'e X-as), en de rôze line is it proses foar ynhâldfernijing.

De Lamoda-katalogus befettet miljoenen produkten, en de gegevens wurde de hiele tiid bywurke. Guon kolleksjes geane út moade, nije wurde frijlitten om se te ferfangen, en nije modellen ferskine konstant yn 'e katalogus. Wy besykje te foarsizzen wat nijsgjirrich wêze sil foar ús klanten moarn, dus wy keapje hieltyd nije dingen, fotografearje se en aktualisearje de vitrine.

Roze peaks binne produktupdates, dat is feroaringen yn produkten. It kin sjoen wurde dat de jonges foto's makken, foto's makken, en dan wer! - laden in pakket fan eveneminten.

Lamoda Events gebrûk gefallen

Wy brûke de konstruearre arsjitektuer foar de folgjende operaasjes:

  • Werom status tracking: call-to-action en status tracking fan alle belutsen systemen. Betelling, statusen, fiskalisaasje, notifikaasjes. Hjir testen wy de oanpak, makke ark, sammele alle bugs, skreau dokumintaasje en fertelde ús kollega's hoe't se it brûke.
  • Produktkaarten bywurkje: konfiguraasje, meta-data, skaaimerken. Ien systeem lêst (dat toant), en ferskate skriuwe.
  • E-post, push en sms: de bestelling is sammele, de bestelling is oankommen, it weromkommen is akseptearre, ensfh., der binne in protte fan.
  • Stock, pakhús fernijing - kwantitative fernijing fan items, gewoan nûmers: oankomst by it pakhús, werom. It is needsaaklik dat alle systemen ferbûn mei it reservearjen fan guod operearje mei de meast aktuele gegevens. Op it stuit is it stockupdatesysteem frij kompleks; Kafka sil it ferienfâldigje.
  • Data Analysis (R&D ôfdieling), ML ark, analytics, statistiken. Wy wolle dat ynformaasje transparant is - Kafka is dêr goed geskikt foar.

No is it nijsgjirriger diel oer de grutte bulten en nijsgjirrige ûntdekkingen dy't de ôfrûne seis moannen binne bard.

Design problemen

Litte wy sizze dat wy in nij ding wolle dwaan - bygelyks it heule leveringsproses oermeitsje nei Kafka. No is in diel fan it proses ymplementearre yn Order Processing yn BOB. D'r is in statusmodel efter de oerdracht fan in bestelling nei de leveringstsjinst, beweging nei in tuskenlager, ensfh. D'r is in heule monolith, sels twa, plus in bosk API's wijd oan levering. Se witte folle mear oer levering.

Dit lykje ferlykbere gebieten te wêzen, mar de oarderferwurking yn BOB en it Shipping System hawwe ferskillende statusen. Bygelyks, guon koerierstsjinsten stjoere gjin tuskenstatussen, mar allinich de lêste: "levere" of "ferlern". Oaren, krekt oarsom, rapportearje yn grutte detail oer de beweging fan guod. Elkenien hat syn eigen falidaasjeregels: foar guon is de e-post jildich, wat betsjut dat it ferwurke wurdt; foar oaren is it net jildich, mar de oarder sil noch wurde ferwurke omdat der in telefoannûmer foar kontakt, en immen sil sizze dat sa'n bestelling sil net wurde ferwurke hielendal.

Datastream

Yn it gefal fan Kafka ûntstiet de fraach fan it organisearjen fan de gegevensstream. Dizze taak omfettet it kiezen fan in strategy basearre op ferskate punten; litte wy se allegear trochgean.

Yn ien ûnderwerp of yn ferskate?

Wy hawwe in evenemint spesifikaasje. Yn BOB skriuwe wy dat sa'n en sa'n bestelling besoarge wurde moat, en jouwe oan: it bestelnûmer, de gearstalling dêrfan, guon SKU's en barcodes, ensfh. As it guod by it pakhús oankomt, kin de levering statussen, tiidstempels en alles wat nedich is ûntfange. Mar dan wolle wy updates krije oer dizze gegevens yn BOB. Wy hawwe in omkearde proses foar it ûntfangen fan gegevens fan levering. Is dit itselde barren? Of is dit in aparte útwikseling dy't in eigen ûnderwerp fertsjinnet?

Meast wierskynlik sille se heul gelyk wêze, en de ferlieding om ien ûnderwerp te meitsjen is net ûnbegrûn, om't in apart ûnderwerp aparte konsuminten betsjut, aparte konfiguraasjes, in aparte generaasje fan dit alles. Mar gjin feit.

Nij fjild of nij evenemint?

Mar as jo deselde eveneminten brûke, dan ûntstiet in oar probleem. Bygelyks, net alle leveringssystemen kinne it soarte DTO generearje dat BOB kin generearje. Wy stjoere se de id, mar se bewarje it net om't se it net nedich hawwe, en út it eachpunt fan it begjin fan it evenemint-busproses is dit fjild ferplicht.

As wy yntrodusearje in regel foar evenemint-bus dat dit fjild is ferplichte, dan binne wy ​​twongen om te setten ekstra falidaasje regels yn de BOB of yn de start evenemint handler. Validaasje begjint te fersprieden oer de tsjinst - dit is net heul handich.

In oar probleem is de ferlieding ta inkrementele ûntwikkeling. Wy wurde ferteld dat der wat tafoege wurde moat oan it evenemint, en miskien, as wy der oer tinke, hie it in apart barren wêze moatten. Mar yn ús skema is in apart barren in apart ûnderwerp. In apart ûnderwerp is it heule proses dat ik hjirboppe beskreaun. De ûntwikkelder is oanstriid om gewoan in oar fjild ta te foegjen oan it JSON-skema en it te regenerearjen.

Yn it gefal fan refunds, wy kamen by it evenemint fan eveneminten yn in heal jier. Wy hiene ien meta-evenemint neamd werombetelje update, dy't in typefjild hie dat beskreau wat dizze fernijing eins wie. Hjirtroch hienen wy "prachtige" skeakels mei validators dy't ús fertelden hoe't jo dit evenemint mei dit type validearje kinne.

Event ferzje

Om berjochten yn Kafka te falidearjen kinne jo brûke Avro, mar it wie nedich om der daliks op te lizzen en Confluent te brûken. Yn ús gefal moatte wy foarsichtich wêze mei ferzjen. It sil net altyd mooglik wêze om berjochten fan it replikalogboek opnij te lêzen, om't it model "lofts" is. Yn prinsipe docht bliken om ferzjes te bouwen sadat it model efterút kompatibel is: meitsje bygelyks in fjild tydlik opsjoneel. As de ferskillen te sterk binne, begjinne wy ​​​​yn in nij ûnderwerp te skriuwen, en oerdrage kliïnten as se de âlde lêze.

Garandearre lêsfolchoarder fan partysjes

Underwerpen binnen Kafka binne ferdield yn partysjes. Dit is net heul wichtich wylst wy entiteiten en útwikselingen ûntwerpe, mar it is wichtich as jo beslute hoe't jo it konsumearje en skaalje.

Yn it gewoane gefal skriuwe jo ien ûnderwerp yn Kafka. Standert wurdt ien partition brûkt, en alle berjochten yn dit ûnderwerp geane dernei. En de konsumint lêst dizze berjochten opienfolgjend. Litte wy no sizze dat wy it systeem moatte útwreidzje sadat berjochten wurde lêzen troch twa ferskillende konsuminten. As jo ​​bygelyks SMS ferstjoere, dan kinne jo Kafka fertelle om in ekstra partysje te meitsjen, en Kafka sil begjinne om de berjochten yn twa dielen te splitsen - de helte hjir, de helte hjir.

Hoe ferdielt Kafka se? Elk berjocht hat in lichem (wêryn wy JSON opslaan) en in kaai. Jo kinne in hash-funksje taheakje oan dizze kaai, dy't sil bepale hokker partition it berjocht sil gean yn.

Yn ús gefal mei restitúsje is dit wichtich, as wy twa partysjes nimme, dan is der in kâns dat in parallelle konsumint it twadde evenemint foar de earste ferwurket en d'r sil problemen wêze. De hashfunksje soarget derfoar dat berjochten mei deselde kaai yn deselde partysje einigje.

Eveneminten vs kommando's

Dit is in oar probleem dat wy tsjinkamen. Evenemint is in bepaald barren: wy sizze dat der earne wat bard is (wat_barde), bygelyks in item waard annulearre of in weromjefte barde. As immen harket nei dizze eveneminten, dan neffens "item annulearre," de werombetelje entiteit wurdt oanmakke, en "werombetelle barde" wurdt skreaun earne yn de opset.

Mar normaal, as jo eveneminten ûntwerpe, wolle jo se net om 'e nocht skriuwe - jo fertrouwe op it feit dat immen se sil lêze. Der is in hege ferlieding om te skriuwen net eat_happened (item_cancelled, refund_refunded), mar eat_should_be_done. Bygelyks, item is klear om werom te wurden.

Oan 'e iene kant suggerearret it hoe't it evenemint brûkt wurde sil. Oan 'e oare kant klinkt it folle minder as in normale barrensnamme. Boppedat is it hjir net fier fan it do_something kommando. Mar jo hawwe gjin garânsje dat immen lêze dit evenemint; en as jo it lêze, dan lêze jo it mei súkses; en as jo it mei súkses lêze, dan diene jo wat, en dat wie suksesfol. Op it momint dat in evenemint do_something wurdt, wurdt feedback nedich, en dat is in probleem.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Yn asynchrone útwikseling yn RabbitMQ, as jo it berjocht lêze, gean dan nei http, jo hawwe in antwurd - op syn minst dat it berjocht ûntfongen is. As jo ​​​​nei Kafka skriuwe, is der in berjocht dat jo oan Kafka skreaun hawwe, mar jo witte neat oer hoe't it ferwurke is.

Dêrom moasten wy yn ús gefal in reaksje-evenemint ynfiere en tafersjoch opsette, sadat as safolle eveneminten ferstjoerd waarden, nei sa'n en sa'n tiid itselde oantal antwurd-eveneminten komme soe. As dat net bart, dan liket der wat mis gien te wêzen. Bygelyks, as wy it evenemint "item_ready_to_refund" stjoerd hawwe, ferwachtsje wy dat in weromjefte sil wurde makke, it jild wurdt weromjûn oan 'e kliïnt, en it evenemint "money_refunded" sil nei ús stjoerd wurde. Mar dit is net wis, dus tafersjoch is nedich.

Nuances

Der is in frij dúdlik probleem: as jo lêze fan in ûnderwerp sequentially, en jo hawwe wat min berjocht, de konsumint sil falle, en do silst net gean fierder. Do hast nedich stopje alle konsuminten, commit offset fierder om fierder te lêzen.

Wy wisten der fan, wy rekkenen der op, en dochs barde it. En dit barde om't it evenemint jildich wie út it eachpunt fan eveneminten-bus, it evenemint wie jildich út it eachpunt fan 'e applikaasjevalidator, mar it wie net jildich út it eachpunt fan PostgreSQL, om't yn ús ien systeem MySQL mei UNSIGNED INT, en yn it nij skreaune systeem hie PostgreSQL gewoan mei INT. Syn maat is in bytsje lytser, en de Id paste net. Symfony stoar mei in útsûndering. Wy hawwe fansels de útsûndering fongen, om't wy der op fertrouden en dizze offset soene dwaan, mar dêrfoar woene wy ​​de probleemteller ferheegje, om't it berjocht sûnder sukses ferwurke waard. De tellers yn dit projekt binne ek yn 'e databank, en Symfony hat al sletten kommunikaasje mei de databank, en de twadde útsûndering fermoarde it hiele proses sûnder in kâns om te begean offset.

De tsjinst lei in skoft - gelokkich, mei Kafka is dat net sa slim, want de berjochten bliuwe. As it wurk is restaurearre, kinne jo it lêzen foltôgje. It is noflik.

Kafka hat de mooglikheid om in willekeurige offset yn te stellen fia tooling. Mar om dit te dwaan, moatte jo alle konsuminten stopje - yn ús gefal, tariede in aparte release wêryn d'r gjin konsuminten, weryndielingen sille wêze. Dan kinne jo yn Kafka de offset troch tooling ferskowe, en it berjocht sil trochgean.

In oare nuânse - replikaasjelog vs rdkafka.so - is relatearre oan de spesifikaasjes fan ús projekt. Wy brûke PHP, en yn PHP kommunisearje as regel alle biblioteken mei Kafka fia de rdkafka.so repository, en dan is der in soarte fan wrapper. Miskien binne dat ús persoanlike swierrichheden, mar it die bliken dat it gewoan op 'e nij lêze fan in stik fan wat wy al lêzen hiene net sa maklik is. Yn 't algemien wiene d'r softwareproblemen.

Werom nei de spesifikaasjes fan wurkjen mei partysjes, it is rjocht skreaun yn 'e dokumintaasje konsuminten >= ûnderwerp partysjes. Mar ik kaam der folle letter achter as ik woe. As jo ​​​​skaal wolle en twa konsuminten hawwe, moatte jo op syn minst twa partysjes hawwe. Dat is, as jo ien partysje hiene wêryn 20 tûzen berjochten sammele hawwe, en jo hawwe in nije makke, sil it oantal berjochten net gau lykmakke wurde. Dêrom, om twa parallelle konsuminten te hawwen, moatte jo mei partysjes omgean.

Monitoring

Ik tink dat de wize wêrop wy it folgjen noch dúdliker wurde sil hokker problemen der binne yn de besteande oanpak.

Wy berekkenje bygelyks hoefolle produkten yn 'e databank har status koartlyn feroare hawwe, en dêrtroch soene eveneminten moatte bard wêze op basis fan dizze feroarings, en wy stjoere dit nûmer nei ús tafersjochsysteem. Dan krije wy fan Kafka it twadde nûmer, hoefolle eveneminten binne eins opnommen. Fansels moat it ferskil tusken dizze twa nûmers altyd nul wêze.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Dêrneist moatte jo kontrolearje hoe't de produsint docht, oft eveneminten-bus ûntfongen berjochten, en hoe't de konsumint docht. Bygelyks, yn 'e diagrammen hjirûnder, docht Refund Tool it goed, mar BOB hat dúdlik wat problemen (blauwe toppen).

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Ik haw al fertraging fan konsumintgroep neamd. Dit is rûchwei it oantal net-lêzen berjochten. Yn 't algemien wurkje ús konsuminten fluch, dus de efterstân is normaal 0, mar soms kin d'r in koarte termyn pyk wêze. Kafka kin dit út 'e doaze dwaan, mar jo moatte in bepaald ynterval ynstelle.

Der is in projekt hoaledat sil jaan jim mear ynformaasje oer Kafka. It brûkt gewoan de konsumintgroep API om de status te jaan fan hoe't dizze groep docht. Neist OK en mislearre is d'r in warskôging, en jo kinne útfine dat jo konsuminten it tempo fan produksje net kinne omgean - se hawwe gjin tiid om te korrizearjen wat skreaun is. It systeem is frij tûk en maklik te brûken.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Dit is hoe't it API-antwurd derút sjocht. Hjir is de groep bob-live-fifa, partition refund.update.v1, status OK, lag 0 - de lêste finale offset sa en sa.

Underfining yn it ûntwikkeljen fan de Refund Tool-tsjinst mei in asynchrone API op Kafka

Monitoring updated_by SLA (fêst) Ik haw al neamd. Bygelyks, it produkt is feroare yn de status dat it klear is foar werom. Wy ynstallearje Cron, dy't seit dat as yn 5 minuten dit objekt is net gien om werombetelje (wy werom jild fia betelling systemen hiel fluch), dan wat gie perfoarst mis, en dit is perfoarst in gefal foar stipe. Dêrom nimme wy gewoan Cron, dy't sokke dingen lêst, en as se grutter binne as 0, dan stjoert it in warskôging.

Om gearfetsje, it brûken fan eveneminten is handich wannear:

  • ynformaasje is nedich troch ferskate systemen;
  • it resultaat fan ferwurking is net wichtich;
  • der binne in pear eveneminten of lytse eveneminten.

It liket derop dat it artikel in heul spesifyk ûnderwerp hat - asynchrone API op Kafka, mar yn ferbân mei it soe ik in protte dingen tagelyk oanbefelje wolle.
Earst, folgjende HighLoad++ wy moatte wachtsje oant novimber, yn april komt der in ferzje fan Sint-Petersburch, en yn juny sille wy prate oer hege loads yn Novosibirsk.
Twadder is de skriuwer fan it rapport, Sergei Zaika, lid fan 'e Programmakommisje fan ús nije konferinsje oer kennisbehear KnowledgeConf. De konferinsje is ien dei, sil plakfine op 26 april, mar har programma is heul yntinsyf.
En it sil yn maaie wêze PHP Ruslân и RIT++ (mei DevOpsConf ynbegrepen) - jo kinne dêr ek jo ûnderwerp foarstelle, prate oer jo ûnderfining en kleie oer jo gevulde kegels.

Boarne: www.habr.com

Add a comment