Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Wat kéint esou eng grouss Firma wéi Lamoda zwéngen, mat engem streamlined Prozess an Dosende vu verbonne Servicer, seng Approche wesentlech ze änneren? Motivatioun ka ganz anescht sinn: vu legislative bis zum Wonsch ze experimentéieren, deen an all Programméierer inherent ass.

Mä dat heescht net, datt Dir net op zousätzlech Virdeeler zielen kann. De Sergey Zaika wäert Iech soen wat genau Dir kënnt gewannen wann Dir den Event-driven API op Kafka implementéiert (puerald). Et gëtt definitiv och iwwer grouss Schëss an interessant Entdeckungen geschwat - d'Experiment kann net ouni si maachen.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Verzichterklärung: Dësen Artikel baséiert op Materialien vun engem Meetup deen de Sergey am November 2018 op HighLoad++ ofgehalen huet. Dem Lamoda seng Live-Erfahrung mam Kafka ze schaffen huet Nolauschterer net manner ugezunn wéi aner Berichter um Zäitplang. Mir mengen dat ass en exzellent Beispill vun der Tatsaach, datt Dir ëmmer wéi-minded Leit fannen kann a soll, an d'Organisateuren vun HighLoad++ wäert weider probéieren eng Atmosphär ze schafen, déi dozou bäidroen.

Iwwer de Prozess

Lamoda ass eng grouss E-Commerce Plattform déi säin eegene Kontaktzentrum, Liwwerservice (a vill Filialen), e Fotostudio, e risege Lagerhaus huet, an all dat leeft op senger eegener Software. Et ginn Dosende vu Bezuelmethoden, b2b Partner déi e puer oder all vun dëse Servicer benotze kënnen an déi aktuell Informatioun iwwer hir Produkter wësse wëllen. Zousätzlech funktionnéiert Lamoda nieft der russescher Federatioun an dräi Länner an do ass alles e bëssen anescht. Am Ganzen ginn et wahrscheinlech méi wéi honnert Weeër fir eng nei Bestellung ze konfiguréieren, déi op seng eege Manéier veraarbecht muss ginn. All dëst funktionnéiert mat Hëllef vun Dosende vu Servicer, déi heiansdo op net offensichtlech Manéier kommunizéieren. Et gëtt och en zentrale System deem seng Haaptverantwortung d'Bestellungsstatus ass. Mir nennen hatt BOB, ech schaffen mat hatt.

Remboursement Tool mat Event-Undriff API

D'Wuert Event-Undriff ass zimmlech gehackt; e bësse méi wäit wäerte mir méi detailléiert definéieren wat domat gemengt ass. Ech fänken un mam Kontext an deem mir décidéiert hunn d'Evenementsgedriwwen API Approche zu Kafka ze probéieren.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

An all Geschäft, nieft Bestellungen fir déi Cliente bezuelen, ginn et Zäiten wou de Buttek verlaangt ass Suen zréckzeginn, well de Produit net dem Client gepasst huet. Dëst ass e relativ kuerze Prozess: mir klären d'Informatioun, wann néideg, an iwwerweisen d'Suen.

Mä de Retour gouf méi komplizéiert wéinst Ännerungen an der Gesetzgebung, a mir hu missen en separaten Mikroservice dofir ëmsetzen.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Eis Motivatioun:

  1. Gesetz FZ-54 - kuerz, d'Gesetz erfuerdert de Steierbüro iwwer all Währungstransaktioun ze mellen, sief et e Retour oder eng Empfang, bannent enger zimlech kuerzer SLA vun e puer Minutten. Mir, als E-Commerce Firma, maachen zimmlech vill Operatiounen. Technesch heescht dat nei Verantwortung (an dofir en neie Service) a Verbesserungen an all involvéiert Systemer.
  2. BOB gedeelt ass en internen Projet vun der Firma fir de BOB vun enger grousser Zuel vun Net-Kärverantwortung ze entlaaschten an hir Gesamtkomplexitéit ze reduzéieren.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Dëst Diagramm weist d'Haapt Lamoda Systemer. Elo sinn déi meescht vun hinnen méi engem Konstellatioun vun 5-10 microservices ronderëm e verrëngeren monolith. Si wuessen lues a lues, awer mir probéieren se méi kleng ze maachen, well d'Ausschaffe vum Fragment, deen an der Mëtt ausgewielt gëtt, grujeleg ass - mir kënnen et net erlaben ze falen. Mir si gezwongen all Austausch (Pfeiler) ze reservéieren an d'Tatsaach ze berücksichtegen datt jidderee vun hinnen als net verfügbar ass.

BOB huet och zimlech vill Austausch: Bezuelsystemer, Liwwersystemer, Notifikatiounssystemer, asw.

Technesch BOB ass:

  • ~ 150k Zeilen vum Code + ~ 100k Zeilen vun Tester;
  • php7.2 + Zend 1 & Symfony Komponente 3;
  • > 100 APIen & ~ 50 Outbound Integratiounen;
  • 4 Länner mat hirer eegener Geschäftslogik.

BOB z'installéieren ass deier a schmerzhaf, d'Quantitéit u Code a Probleemer déi et léist ass sou datt keen alles an de Kapp setzen kann. Am Allgemengen, ginn et vill Grënn et ze vereinfachen.

Retour Prozess

Am Ufank sinn zwee Systemer am Prozess involvéiert: BOB a Bezuelung. Elo erschéngen nach zwee:

  • Fiskaliséierungsservice, dee sech ëm Problemer mat der Fiskaliséierung a Kommunikatioun mat externe Servicer këmmert.
  • Remboursement Tool, deen einfach nei Austausch enthält fir de BOB net opzebauen.

Elo gesäit de Prozess esou aus:

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

  1. BOB kritt eng Demande fir e Remboursement.
  2. BOB schwätzt iwwer dëst Remboursement Tool.
  3. De Remboursement Tool seet Bezuelung: "Gitt d'Suen zréck."
  4. Bezuelung gëtt d'Suen zréck.
  5. Remboursement Tool a BOB synchroniséieren Statuse mateneen, well se fir de Moment allebéid brauchen. Mir sinn nach net prett fir komplett op de Remboursement Tool ze wiesselen, well de BOB en UI huet, Berichter fir Comptabilitéit, an allgemeng vill Daten déi net sou einfach kënne transferéiert ginn. Dir musst op zwee Still sëtzen.
  6. D'Demande fir Fiskaliséierung geet ewech.

Als Resultat hu mir eng Zort Eventbus um Kafka gemaach - Event-Bus, op deem alles ugefaang huet. Hurra, elo hu mir en eenzege Punkt vum Echec (Sarkasmus).

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

D'Virdeeler an Nodeeler sinn zimlech offensichtlech. Mir hunn e Bus gemaach, dat heescht datt elo all Servicer dovun ofhänken. Dëst vereinfacht den Design, awer stellt en eenzege Punkt vun Echec an de System. Kafka wäert Crash, de Prozess wäert ophalen.

Wat ass eng Event-Undriff API

Eng gutt Äntwert op dës Fro ass am Bericht vum Martin Fowler (GOTO 2017) "Déi vill Bedeitunge vun Event-Driven Architecture".

Kuerz wat mir gemaach hunn:

  1. Wrap all asynchronen Austausch iwwer Evenementer Stockage. Amplaz vun engem informéieren all interesséiert Konsument iwwer e Status änneren iwwert d'Netz, mir schreiwen en Event iwwer e Status änneren op eng zentraliséiert Stockage, a Konsumenten interesséiert am Thema liesen alles wat vun do schéngt.
  2. D'Evenement an dësem Fall ass eng Notifikatioun (Notifikatiounen) datt iergendwou eppes geännert huet. Zum Beispill huet d'Bestellungsstatus geännert. E Konsument, deen un e puer Donnéeën interesséiert, déi de Statusännerung begleeden, déi net an der Notifikatioun abegraff sinn, kann säi Status selwer erausfannen.
  3. Déi maximal Optioun ass vollwäerteg Event Sourcing, Staat Transfert, a wéi engem Fall all déi néideg Informatioune fir d'Veraarbechtung enthält: wou se hierkënnt a wéi en Zoustand et ass, wéi genau d'Donnéeën geännert hunn, asw.. Déi eenzeg Fro ass d'Machbarkeet an d'Quantitéit un Informatioun déi Dir Iech leeschte kënnt ze späicheren.

Als Deel vum Start vum Remboursement Tool hu mir déi drëtt Optioun benotzt. Dës vereinfacht Eventveraarbechtung well et kee Besoin war fir detailléiert Informatioun ze extrahieren, plus et huet de Szenario eliminéiert wou all neit Event e Burst generéiert fir ze klären Ufroe vu Konsumenten.

Remboursement Tool Service net gelueden, Also Kafka gëtt et méi e Goût vum Pen wéi eng Noutwennegkeet. Ech mengen net, datt wann de Remboursement Service eng héich-Laascht Projet gouf, Betrib wier frou.

Async Austausch AS IS

Fir asynchronen Austausch benotzt de PHP Departement normalerweis RabbitMQ. Mir hunn d'Donnéeën fir d'Ufro gesammelt, se an eng Schlaang gesat, an de Konsument vum selwechte Service huet se gelies a geschéckt (oder net geschéckt). Fir d'API selwer benotzt Lamoda aktiv Swagger. Mir designen eng API, beschreiwen et am Swagger, a generéiere Client- a Servercode. Mir benotzen och e liicht verstäerkte JSON RPC 2.0.

Op e puer Plazen ginn ESB Bussen benotzt, e puer liewen op activeMQ, awer am Allgemengen, RabbitMQ - Standard.

Async Austausch TO BE

Wann Dir den Austausch iwwer Eventbus designt, kann eng Analogie verfollegt ginn. Mir beschreiwen ähnlech zukünfteg Datenaustausch duerch Eventstrukturbeschreiwungen. D'yaml Format, mir hunn d'Code Generatioun selwer ze maachen, de Generator erstellt DTOs no der Spezifizéierung a léiert Clienten a Servere mat hinnen ze schaffen. Generatioun geet an zwou Sproochen - golang an php. Dëst hëlleft Bibliothéiken konsequent ze halen. De Generator ass a Golang geschriwwen, dofir krut hien den Numm gogi.

Event-sourcing op Kafka ass eng typesch Saach. Et gëtt eng Léisung vun der Haaptentreprise Versioun vu Kafka Confluent, et gëtt nakadi, eng Léisung vun eisen Domain Bridder Zalando. Eis Motivatioun fir mat Vanille Kafka unzefänken - dat heescht, d'Léisung fräi ze loossen, bis mir endlech décidéieren, ob mir se iwwerall benotze wäerten, an och eis Spillraum a Verbesserunge loossen: mir wëllen Ënnerstëtzung fir eis JSON RPC 2.0, Generatoren fir zwou Sproochen a loosst eis kucken wat soss.

Et ass ironesch datt och an esou engem gléckleche Fall, wann et e bal ähnlecht Geschäft gëtt, Zalando, deen eng ongeféier ähnlech Léisung gemaach huet, mir se net effektiv benotze kënnen.

D'architektonescht Muster beim Start ass wéi follegt: mir liesen direkt vum Kafka, awer schreiwen nëmmen duerch Eventer-Bus. Et gëtt vill prett fir am Kafka ze liesen: Broker, Balancer, an et ass méi oder manner prett fir horizontale Skala, ech wollt dat behalen. Mir wollten den Opnahmen duerch ee Gateway aka Events-Bus fäerdeg maachen, an hei ass firwat.

Evenementer-Bus

Oder en Eventbus. Dëst ass einfach e stateless http Paart, deen e puer wichteg Rollen iwwerhëlt:

  • Produzéiert Validatioun - mir kontrolléieren ob d'Evenementer eise Spezifikatioune entspriechen.
  • Event Master System, dat ass, dat ass den Haaptgrond an eenzege System an der Firma, datt d'Fro beäntwert vun deenen Evenementer mat deenen Strukturen gëlteg considéréiert ginn. Validatioun beinhalt einfach Datentypen an Enums fir den Inhalt strikt ze spezifizéieren.
  • Hash Funktioun fir Sharing - d'Kafka Message Struktur ass Schlësselwäert a mam Hash vum Schlëssel gëtt berechent wou se se setzen.

Firwat

Mir schaffen an enger grousser Firma mat engem streamlined Prozess. Firwat eppes änneren? Dëst ass en Experiment, a mir erwaarden e puer Virdeeler.

1:n+1 Austausch (een op vill)

Kafka mécht et ganz einfach nei Konsumenten un der API ze verbannen.

Loosst eis soen datt Dir e Verzeechnes hutt deen Dir braucht a verschiddene Systemer gläichzäiteg (an e puer neier) um neiste Stand ze halen. Virdrun hu mir e Bündel erfonnt deen Set-API implementéiert huet, an de Mastersystem gouf iwwer Konsumentenadressen informéiert. Elo schéckt de Mastersystem Updates zum Thema, a jiddereen deen interesséiert ass liest et. En neie System ass erschéngt - mir hunn et fir d'Thema ugemellt. Jo, och Bündel, awer méi einfach.

Am Fall vum Remboursement-Tool, wat e Stéck BOB ass, ass et bequem fir eis se duerch Kafka synchroniséiert ze halen. Bezuelen seet, datt d'Suen zréck goufen: BOB, RT fonnt iwwer dëst, geännert hir statuses, Fiskalisatioun Service fonnt iwwer dëst an erausginn engem kontrolléieren.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Mir hu Pläng fir en vereenegt Notifikatiounsservice ze kreéieren deen de Client iwwer Neiegkeeten iwwer seng Bestellung / Retour informéiert. Elo ass dës Verantwortung tëscht Systemer verdeelt. Et wäert genuch sinn fir den Notifikatiounsservice ze léieren fir relevant Informatioun vu Kafka ze fangen an dorop ze reagéieren (an dës Notifikatiounen an anere Systemer auszeschalten). Keen neien direkten Austausch gëtt erfuerderlech.

Datadriwwer

Informatioun tëscht Systemer gëtt transparent - egal wéi eng "bluddeg Entreprise" Dir hutt an egal wéi plump Äre Réckstand ass. Lamoda huet en Data Analytics Departement deen Daten aus Systemer sammelt an se an eng wiederverwendbar Form setzt, souwuel fir Geschäfter wéi och fir intelligent Systemer. Kafka erlaabt Iech hinnen séier vill Daten ze ginn an dësen Informatiounsfloss um neiste Stand ze halen.

Replikatiounsprotokoll

Messagen verschwannen net nodeems se gelies goufen, wéi am RabbitMQ. Wann en Event genuch Informatioun fir d'Veraarbechtung enthält, hu mir eng Geschicht vu rezenten Ännerungen am Objet, an, wann Dir wëllt, d'Fäegkeet dës Ännerungen z'applizéieren.

D'Späicherzäit vum Replikatiounsprotokoll hänkt vun der Intensitéit vum Schreiwen op dëst Thema of; Kafka erlaabt Iech flexibel Limiten op Späicherzäit an Datevolumen ze setzen. Fir intensiv Themen ass et wichteg datt all Konsumenten Zäit hunn d'Informatioun ze liesen ier se verschwënnt, och am Fall vu kuerzfristeg Inoperabilitéit. Et ass normalerweis méiglech Daten ze späicheren fir Unitéiten vun Deeg, wat genuch fir Ënnerstëtzung ass.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Als nächst, e klengen Erzielung vun der Dokumentatioun, fir déi, déi net mam Kafka vertraut sinn (d'Bild ass och aus der Dokumentatioun)

AMQP huet Schlaangen: mir schreiwen Messagen op eng Schlaang fir de Konsument. Typesch gëtt eng Schlaang vun engem System mat der selwechter Geschäftslogik veraarbecht. Wann Dir e puer Systemer matdeele musst, kënnt Dir d'Applikatioun léieren a verschidde Schlaangen ze schreiwen oder den Austausch mam Fanout-Mechanismus ze konfiguréieren, deen se selwer klonen.

Kafka huet eng ähnlech Abstraktioun Sujet, an deenen Dir Messagen schreift, awer se verschwannen net nom Liesen. Par défaut, wann Dir mat Kafka verbënnt, kritt Dir all Messagen an hutt d'Optioun fir ze späicheren wou Dir opgehalen hutt. Dat ass, Dir liest sequenziell, Dir däerft de Message net als gelies markéieren, awer d'Id späicheren, aus där Dir da weider liesen kënnt. D'Id, op där Dir niddergelooss hutt, gëtt Offset genannt, an de Mechanismus ass eng Verpflichtungsoffset.

Deementspriechend kënne verschidde Logik ëmgesat ginn. Zum Beispill hu mir BOB a 4 Instanzen fir verschidde Länner - Lamoda ass a Russland, Kasachstan, Ukraine, Wäissrussland. Well se separat ofgebaut ginn, hu se liicht ënnerschiddlech Konfiguratiounen an hir eege Geschäftslogik. Mir weisen am Message op wéi ee Land et sech bezitt. All BOB Konsument an all Land liest mat enger anerer groupId, a wann de Message net fir si gëlt, sprangen se et, d.h. direkt engagéiert offset +1. Wann datselwecht Thema vun eisem Bezuelungsservice gelies gëtt, da mécht et dat mat enger separater Grupp, an dofir kräizen d'Offsets net.

Event Ufuerderunge:

  • Donnéeën Vollständegkeet. Ech hätt gär datt d'Evenement genuch Donnéeën huet fir datt se veraarbecht kënne ginn.

  • Integritéit Mir delegéieren Events-Bus d'Verifizéierung datt d'Evenement konsequent ass an et kann et veraarbecht.
  • D'Bestellung ass wichteg. Am Fall vun engem Retour si mir gezwongen mat der Geschicht ze schaffen. Mat Notifikatiounen ass d'Bestellung net wichteg, wa se homogen Notifikatiounen sinn, wäert d'E-Mail d'selwecht sinn, egal wéi eng Bestellung als éischt ukomm ass. Am Fall vun engem Remboursement gëtt et e kloere Prozess; wa mir d'Bestellung änneren, entstinn Ausnahmen, de Remboursement gëtt net erstallt oder veraarbecht - mir kommen an engem anere Status.
  • Konsistenz. Mir hunn e Geschäft, an elo kreéiere mir Eventer amplaz vun enger API. Mir brauchen e Wee fir séier a bëlleg Informatioun iwwer nei Eventer an Ännerungen un existent un eis Servicer ze vermëttelen. Dëst gëtt erreecht duerch eng gemeinsam Spezifizéierung an engem separaten Git Repository a Code Generatoren. Dofir sinn Clienten a Serveren a verschiddene Servicer koordinéiert.

Kafka zu Lamoda

Mir hunn dräi Kafka Installatiounen:

  1. Logbicher;
  2. R&D;
  3. Evenementer-Bus.

Haut schwätze mer nëmmen iwwer de leschte Punkt. Bei Eventer-Bus hu mir net ganz grouss Installatiounen - 3 Broker (Server) an nëmmen 27 Themen. Als Regel, ass een Thema ee Prozess. Awer dëst ass en subtile Punkt, a mir wäerten et elo beréieren.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Uewen ass d'rps Grafik. De Remboursementprozess ass mat enger türkiser Linn markéiert (jo, déi op der X Achs), an déi rosa Linn ass den Inhalt Update Prozess.

De Lamoda Katalog enthält Millioune Produkter, an d'Donnéeën ginn déi ganzen Zäit aktualiséiert. E puer Kollektiounen ginn aus der Moud eraus, nei ginn verëffentlecht fir se z'ersetzen, an nei Modeller erschéngen stänneg am Katalog. Mir probéieren virauszesoen, wat fir eis Clienten muer interessant wäert sinn, sou datt mir permanent nei Saachen kafen, se fotograféieren an d'Vitrine aktualiséieren.

Rosa Peaks sinn Produktupdates, dat heescht Ännerungen an de Produkter. Et gesäit een datt d'Jongen Fotoen gemaach hunn, Fotoen gemaach hunn, an dann erëm! - e Pak vun Eventer gelueden.

Lamoda Eventer benotzt Fäll

Mir benotzen déi konstruéiert Architektur fir déi folgend Operatiounen:

  • Retour Status Tracking: Call-to-action a Status Tracking vun all involvéierten Systemer. Bezuelung, Status, Fiskaliséierung, Notifikatiounen. Hei hu mir d'Approche getest, Tools gemaach, all Bugs gesammelt, Dokumentatioun geschriwwen an eise Kollegen gesot wéi se se benotzen.
  • Update Produktkaarten: Configuratioun, Meta-Daten, Charakteristiken. Ee System liest (wat weist), a verschidde schreiwen.
  • E-Mail, Push an SMS: d'Bestellung ass gesammelt, d'Bestellung ass ukomm, d'Retour ass ugeholl, asw., et gi vill vun hinnen.
  • Stock, Lager Erneierung - quantitativ Aktualiséierung vun Artikelen, just Zuelen: Arrivée am Lager, Retour. Et ass néideg datt all Systemer verbonne mat der Reservéierung vu Wueren mat den aktuellsten Daten funktionnéieren. De Moment ass de Stock Update System zimlech komplex; Kafka wäert et vereinfachen.
  • Datenanalyse (R&D Departement), ML Tools, Analyse, Statistiken. Mir wëllen datt d'Informatioun transparent ass - de Kafka ass gutt dofir.

Elo de méi interessanten Deel iwwer déi grouss Bumps an interessant Entdeckungen déi an de leschte sechs Méint geschitt sinn.

Design Problemer

Loosst eis soen, mir wëllen eng nei Saach maachen - zum Beispill de ganze Liwwerungsprozess op Kafka iwwerdroen. Elo gëtt en Deel vum Prozess am Order Processing am BOB implementéiert. Et gëtt e Statusmodell hannert dem Transfert vun enger Bestellung un de Liwwerservice, Bewegung an en Zwëschelager, asw. Et gëtt e ganze Monolith, souguer zwee, plus eng Rëtsch APIen fir d'Liwwerung gewidmet. Si wëssen vill méi iwwer Liwwerung.

Dës schéngen ähnlech Beräicher ze sinn, awer d'Bestellungsveraarbechtung am BOB an de Shipping System hu verschidde Statusen. Zum Beispill, e puer Courrier Servicer schécken net Tëschenzäit Status, mä nëmmen déi lescht: "geliwwert" oder "verluer". Anerer, am Géigendeel, berichten am Detail iwwer d'Bewegung vu Wueren. Jiddereen huet seng eege Validatiounsregelen: fir e puer ass d'E-Mail gëlteg, dat heescht datt se veraarbecht gëtt; fir anerer ass et net valabel, mä d'Bestellung wäert nach veraarbecht ginn, well et eng Telefonsnummer fir Kontakt ass, an een wäert soen, datt esou eng Commande guer net veraarbecht ginn.

Daten Stream

Am Fall vu Kafka stellt sech d'Fro op d'Organisatioun vum Datefloss. Dës Aufgab beinhalt d'Auswiel vun enger Strategie baséiert op e puer Punkten; loosst eis duerch se all goen.

An engem Thema oder an verschiddenen?

Mir hunn eng Event Spezifizéierung. Am BOB schreiwen mir datt esou an esou eng Bestellung muss geliwwert ginn, an uginn: d'Bestellungsnummer, seng Zesummesetzung, e puer SKUs a Barcoden, asw. Wann d'Wueren an de Lager ukommen, kann d'Liwwerung Statusen, Zäitstempel an alles wat néideg ass. Awer dann wëlle mir Updates iwwer dës Donnéeën am BOB kréien. Mir hunn e ëmgedréint Prozess fir Daten aus der Liwwerung ze kréien. Ass dëst datselwecht Evenement? Oder ass dëst en separaten Austausch deen säin eegent Thema verdéngt?

Wahrscheinlech wäerte se ganz ähnlech sinn, an d'Versuchung fir en Thema ze maachen ass net onbegrënnt, well en separaten Thema bedeit separat Konsumenten, separat Konfiguratiounen, eng separat Generatioun vun all deem. Awer net e Fakt.

Neit Feld oder neit Event?

Awer wann Dir déiselwecht Eventer benotzt, da entsteet en anere Problem. Zum Beispill, net all Liwwersystemer kënnen d'Aart vun DTO generéieren déi de BOB generéiere kann. Mir schécken hinnen d'ID, awer se späicheren se net well se se net brauchen, a vun der Siicht vum Event-Busprozess unzefänken, ass dëst Feld erfuerderlech.

Wa mir eng Regel fir Event-Bus aféieren datt dëst Feld erfuerderlech ass, da si mir gezwongen zousätzlech Validatiounsregelen am BOB oder am Start Event Handler ze setzen. D'Validatioun fänkt un am ganze Service ze verbreeden - dëst ass net ganz bequem.

En anere Problem ass d'Versuchung fir inkrementell Entwécklung. Mir kréien gesot datt eppes un d'Evenement bäigefüügt muss ginn, a vläicht, wa mir driwwer nodenken, sollt et en separaten Event gewiescht sinn. Awer an eisem Schema ass e separaten Event e separat Thema. En separat Thema ass de ganze Prozess deen ech uewen beschriwwen hunn. Den Entwéckler ass versicht einfach en anert Feld am JSON Schema ze addéieren an et ze regeneréieren.

Am Fall vun Remboursementer, mir ukomm am Event vun Evenementer an en halleft Joer. Mir haten ee Meta-Event genannt Remboursement Update, deen en Typfeld hat dat beschreift wat dësen Update tatsächlech war. Wéinst dësem hu mir "wonnerbar" Schalter mat Valideuren, déi eis gesot hunn wéi dëst Evenement mat dësem Typ validéiert gëtt.

Event Versioun

Fir Messagen am Kafka ze validéieren kënnt Dir benotzen Avro, awer et war néideg fir direkt drop ze leeën a Confluent ze benotzen. An eisem Fall musse mir virsiichteg sinn mat der Versioun. Et wäert net ëmmer méiglech sinn Messagen aus dem Replikatiounsprotokoll ze liesen, well de Modell "lénks" ass. Prinzipiell stellt sech eraus fir Versiounen ze bauen sou datt de Modell réckgängeg kompatibel ass: zum Beispill e Feld temporär fakultativ maachen. Wann d'Ënnerscheeder ze staark sinn, fänken mir an engem neien Thema ze schreiwen, an iwwerdroe Clienten wann se déi al liesen.

Garantéiert liesen Uerdnung vun Partitionen

Themen bannent Kafka sinn an Partitionen opgedeelt. Dëst ass net ganz wichteg wärend mir Entitéiten an Austausch designen, awer et ass wichteg wann Dir decidéiert wéi et ze konsuméieren an ze skaléieren.

Am übleche Fall schreift Dir een Thema am Kafka. Par défaut gëtt eng Partition benotzt, an all Messagen an dësem Thema ginn dohinner. An de Konsument liest dës Messagen sequenziell. Loosst eis elo soen, mir mussen de System ausbaue fir datt Messagen vun zwee verschiddene Konsumenten gelies ginn. Wann Dir zum Beispill SMS schéckt, da kënnt Dir dem Kafka soen eng zousätzlech Partition ze maachen, a Kafka fänkt un d'Messagen an zwee Deeler opzedeelen - hallef hei, hallef hei.

Wéi verdeelt de Kafka se? All Message huet e Kierper (an deem mir JSON späicheren) an e Schlëssel. Dir kënnt eng Hashfunktioun un dëse Schlëssel befestegt, déi bestëmmen a wéi eng Partition de Message gitt.

An eisem Fall mat Remboursementer ass dat wichteg, wa mir zwou Partitionen huelen, da besteet d'Chance datt e parallele Konsument dat zweet Event virun der éischter veraarbecht an et gëtt Problemer. D'Hash Funktioun garantéiert datt Messagen mat deemselwechte Schlëssel an der selwechter Partition ophalen.

Eventer vs Kommandoen

Dëst ass en anere Problem dee mir begéint hunn. Event ass e bestëmmten Event: mir soen datt eppes iergendwou geschitt ass (eppes_geschitt), zum Beispill, en Artikel gouf annuléiert oder e Remboursement geschitt. Wann iergendeen op dës Eventer lauschtert, dann laut "Element annuléiert", gëtt d'Remboursement Entitéit erstallt, an "Rückerstattung geschitt" gëtt iergendwou an de Setups geschriwwe ginn.

Awer normalerweis, wann Dir Eventer designt, wëllt Dir se net vergeblech schreiwen - Dir vertraut op d'Tatsaach datt een se liest. Et gëtt eng héich Versuchung ze schreiwen net eppes_geschéien (item_cancelled, refund_refunded), mee eppes_should_be_done. Zum Beispill ass den Artikel prett fir zréckzekommen.

Engersäits proposéiert et wéi d'Evenement benotzt gëtt. Op der anerer Säit kléngt et vill manner wéi en normalen Eventnumm. Ausserdeem ass et net wäit vun hei bis zum do_something Kommando. Mä Dir hutt keng Garantie, datt een dëst Evenement liesen; a wann Dir et liest, da liest Dir et erfollegräich; a wann Dir et erfollegräich gelies hutt, dann hutt Dir eppes gemaach, an dat war Erfolleg. De Moment wou en Event do_eppes gëtt, gëtt Feedback néideg, an dat ass e Problem.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Am asynchronen Austausch am RabbitMQ, wann Dir de Message liest, gitt op http, Dir hutt eng Äntwert - op d'mannst datt de Message kritt gouf. Wann Dir un de Kafka schreift, gëtt et e Message deen Dir un de Kafka geschriwwen hutt, awer Dir wësst näischt iwwer wéi et veraarbecht gouf.

Dofir musse mir an eisem Fall en Äntwertevent aféieren an d'Iwwerwaachung opstellen, fir datt wann esou vill Eventer geschéckt gi sinn, no esou an esou enger Zäit déi selwecht Unzuel vun Äntwertevents ukommen. Wann dat net geschitt, da schéngt eppes falsch gaang ze sinn. Zum Beispill, wa mir den Event "item_ready_to_refund" geschéckt hunn, erwaarden mir datt e Remboursement erstallt gëtt, d'Suen ginn un de Client zréckginn an d'Event "money_refunded" gëtt un eis geschéckt. Awer dëst ass net sécher, dofir ass Iwwerwaachung néideg.

Nuancen

Et gëtt e relativ offensichtleche Problem: Wann Dir vun engem Thema sequenziell liest, an Dir hutt e schlechte Message, wäert de Konsument falen, an Dir wäert net méi wäit goen. Du brauchs stoppen all Konsumenten, engagéieren Offset weider fir weider ze liesen.

Mir woussten doriwwer, mir hunn drop gerechent, an awer ass et geschitt. An dëst ass geschitt well d'Evenement valabel war aus der Siicht vun Eventer-Bus, d'Evenement war valabel aus der Siicht vum Applikatiounsvalidator, awer et war net valabel aus der Siicht vu PostgreSQL, well an eisem eenzege System MySQL mat UNSIGNED INT, an am nei geschriwwe System hat PostgreSQL just mat INT. Seng Gréisst ass e bësse méi kleng, an d'Id passt net. Symfony ass mat enger Ausnam gestuerwen. Mir hunn natierlech d'Ausnam erfaasst, well mir drop drop vertraut hunn, an dës Offset géife maachen, awer virdru wollte mir de Problemteller erhéijen, well de Message ouni Erfolleg veraarbecht gouf. D'Zähler an dësem Projet sinn och an der Datebank, a Symfony huet scho Kommunikatioun mat der Datebank zougemaach, an déi zweet Ausnam huet de ganze Prozess ëmbruecht ouni Chance fir Offset ze engagéieren.

De Service huet e bëssen Zäit geluecht - glécklecherweis ass dat mam Kafka net sou schlecht, well d'Messagen bleiwen. Wann d'Aarbecht restauréiert ass, kënnt Dir se fäerdeg liesen. Et ass bequem.

Kafka huet d'Fäegkeet fir en arbiträren Offset duerch Tooling ze setzen. Mä fir dëst ze maachen, musst Dir all Konsumenten ophalen - an eisem Fall, preparéieren eng separat Verëffentlechung, an där et kee Konsument gëtt, nei Verdeelungen. Dann am Kafka kënnt Dir de Offset duerch Tooling verschwannen, an de Message wäert duerchgoen.

Eng aner Nuance - Replikatiounslog vs rdkafka.so - ass mat de Spezifizitéite vun eisem Projet verbonnen. Mir benotzen PHP, an PHP, als Regel, all Bibliothéiken kommunizéieren mat Kafka duerch d'rdkafka.so Repository, an dann gëtt et eng Zort wrapper. Vläicht sinn dat eis perséinlech Schwieregkeeten, awer et huet sech erausgestallt, datt einfach e Stéck vun deem wat mer scho gelies hunn, net sou einfach ass. Am Allgemengen, do waren Software Problemer.

Zréck op d'Spezifizitéiten vun der Aarbecht mat Partitionen, ass et direkt an der Dokumentatioun geschriwwen Konsumenten >= Thema Partitionen. Mee ech hu vill méi spéit doriwwer erausfonnt wéi ech gär hätt. Wann Dir wëllt Skala an zwee Konsumenten hunn, braucht Dir op d'mannst zwee Partitionen. Dat ass, wann Dir eng Partition hat an där 20 dausend Messagen gesammelt goufen, an Dir hutt eng frësch gemaach, da gëtt d'Zuel vun de Messagen net geschwënn ausgeglach. Dofir, fir zwee parallel Konsumenten ze hunn, musst Dir mat Partitionen këmmeren.

Iwwerwaachung

Ech mengen, wéi mir et iwwerwaachen, wäert nach méi kloer sinn, wéi eng Problemer et an der bestehender Approche gëtt.

Zum Beispill berechene mir wéivill Produkter an der Datebank viru kuerzem hire Status geännert hunn, an deementspriechend sollten d'Evenementer op Basis vun dësen Ännerungen geschéien, a mir schécken dës Zuel un eis Iwwerwaachungssystem. Da kréie mir vum Kafka déi zweet Nummer, wéi vill Eventer tatsächlech opgeholl goufen. Natierlech sollt den Ënnerscheed tëscht dësen zwou Zuelen ëmmer null sinn.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Zousätzlech, musst Dir iwwerwaachen wéi de Produzent mécht, ob Eventer-Bus Messagen kritt hunn, a wéi de Konsument mécht. Zum Beispill, an den Charts hei drënner, mécht de Remboursement Tool gutt, awer de BOB huet kloer e puer Probleemer (blo Peaks).

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Ech ernimmt scho Konsument-Grupp Lag. Grof geschwat, ass dëst d'Zuel vun ongelies Messagen. Am Allgemengen schaffen eis Konsumenten séier, sou datt d'Laag normalerweis 0 ass, awer heiansdo kann et e kuerzfristeg Peak sinn. Kafka kann dëst aus der Këscht maachen, awer Dir musst e gewëssen Intervall setzen.

Et gëtt e Projet begruewendéi Iech méi Informatiounen iwwer Kafka ginn. Et benotzt einfach de Konsument-Grupp API fir de Status ze ginn wéi dës Grupp et mécht. Zousätzlech zu OK a Failed gëtt et eng Warnung, an Dir kënnt erausfannen datt Är Konsumenten net mam Tempo vun der Produktioun eens kënnen - si hunn keng Zäit fir ze korrigéieren wat geschriwwen ass. De System ass ganz intelligent an einfach ze benotzen.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Dëst ass wéi d'API Äntwert ausgesäit. Hei ass de Grupp bob-live-fifa, Partition refund.update.v1, Status OK, Lag 0 - déi lescht Finale Offset esou an esou.

Erfahrung an der Entwécklung vum Refund Tool Service mat enger asynchroner API op Kafka

Iwwerwaachung updated_at SLA (stuckt) Ech hu scho gesot. Zum Beispill, de Produit huet de Status geännert datt et prett ass fir zréck. Mir installéieren Cron, déi seet, datt wann an 5 Minutte dëst Objet net rembourséiert ass (mir zréck Suen duerch Bezuelen Systemer ganz séier), dann ass eppes definitiv falsch gaang, an dëst ass definitiv e Fall fir Ënnerstëtzung. Dofir hu mir einfach Cron, deen esou Saachen liest, a wa se méi wéi 0 sinn, da schéckt en eng Alarm.

Fir ze resuméieren, d'Benotzung vun Eventer ass bequem wann:

  • Informatioun gëtt vu verschiddene Systemer gebraucht;
  • d'Resultat vun der Veraarbechtung ass net wichteg;
  • et gi puer Evenementer oder kleng Evenementer.

Et géif schéngen datt den Artikel e ganz spezifescht Thema huet - asynchron API op Kafka, awer am Zesummenhang mat deem géif ech gär vill Saachen op eemol recommandéieren.
Éischt, nächst HighLoad++ Mir musse bis November waarden, am Abrëll gëtt et eng Versioun vu St.
Zweetens ass den Auteur vum Bericht, Sergei Zaika, Member vum Programmkomitee vun eiser neier Konferenz iwwer Wëssensmanagement KnowledgeConf. D'Konferenz ass een Dag, wäert de 26. Abrëll stattfannen, awer säi Programm ass ganz intensiv.
An et wäert am Mee sinn PHP Russland и RIT++ (mat DevOpsConf abegraff) - Dir kënnt och Äert Thema do proposéieren, iwwer Är Erfahrung schwätzen a beschwéieren iwwer Är gestoppt Kegel.

Source: will.com

Setzt e Commentaire