Historien om Dodo IS-arkitekturen: Back Office Path

Habr forandrer verden. Vi har blogget i over et år. For omtrent seks måneder siden fikk vi ganske logiske tilbakemeldinger fra innbyggerne i Khabrovsk: «Dodo, du sier overalt at du har ditt eget system. Hva slags system er dette? Og hvorfor trenger pizzeriakjeden det?»

Vi satt og tenkte og skjønte at du har rett. Vi prøver å forklare alt med fingrene, men det kommer ut i revne biter og det finnes ingen fullstendig beskrivelse av systemet noe sted. Dermed begynte en lang reise med å samle informasjon, søke etter forfattere og skrive en serie artikler om Dodo IS. La oss gå!

Takk: Takk for at du deler tilbakemeldingen din med oss. Takket være ham beskrev vi endelig systemet, kompilerte en technoradar, og vil snart rulle ut en stor beskrivelse av prosessene våre. Uten dere hadde vi sittet slik i 5 år til.

Historien om Dodo IS-arkitekturen: Back Office Path

Artikkelserie "Hva er Dodo IS?" forteller om:

  1. Tidlig monolitt i Dodo IS (2011-2015). (I prosess...)
  2. Backoffice-sti: separate baser og buss. (Du er her)
  3. Klientsideveien: fasade over basen (2016-2017). (I prosess...)
  4. Historien om ekte mikrotjenester. (2018-2019). (I prosess...)
  5. Ferdig saging av monolitten og stabilisering av arkitekturen. (I prosess...)

Hvis du er interessert i å lære noe annet, skriv i kommentarfeltet.

Uttalelse om den kronologiske beskrivelsen fra forfatteren
Jeg holder jevnlig et møte for nyansatte om temaet "Systemarkitektur". Vi kaller det "Intro til Dodo IS Architecture", og det er en del av onboarding-prosessen for nye utviklere. Ved å snakke i en eller annen form om arkitekturen vår, om dens funksjoner, utviklet jeg en viss historisk tilnærming til beskrivelsen.

Tradisjonelt ser vi på et system som et sett med komponenter (tekniske eller høyere nivå), forretningsmoduler som samhandler med hverandre for å oppnå et eller annet mål. Og selv om et slikt syn er berettiget for design, er det ikke helt egnet for beskrivelse og forståelse. Det er flere grunner:

  • Virkeligheten er annerledes enn den som er på papiret. Ikke alt går som planlagt. Og vi er interessert i hvordan alt faktisk ble og fungerer.
  • Konsekvent presentasjon av informasjon. Faktisk kan du gå kronologisk fra begynnelsen til den nåværende tilstanden.
  • Fra enkelt til komplekst. Ikke universelt, men i vårt tilfelle er det slik. Arkitektur gikk fra enklere tilnærminger til mer komplekse. Ofte, gjennom komplikasjoner, problemer med implementeringshastighet og stabilitet, samt dusinvis av andre egenskaper fra listen over ikke-funksjonelle krav (her godt snakket om kontrasterende kompleksitet med andre krav).

I 2011 så Dodo IS-arkitekturen slik ut:

Historien om Dodo IS-arkitekturen: Back Office Path

I 2020 ble det litt mer komplisert og ble slik:

Historien om Dodo IS-arkitekturen: Back Office Path

Hvordan skjedde denne utviklingen? Hvorfor trengs ulike deler av systemet? Hvilke arkitektoniske beslutninger ble tatt og hvorfor? La oss finne ut av dette i denne artikkelserien.

De første problemene i 2016: hvorfor skal tjenester forlate monolitten?

De første artiklene i serien vil handle om tjenestene som var de første som skilte seg fra monolitten. For å sette deg inn i kontekst, skal jeg fortelle deg hvilke problemer vi hadde i systemet i begynnelsen av 2016, at vi måtte håndtere separasjon av tjenester.

En enkelt MySql-database der alle applikasjoner som eksisterte på den tiden i Dodo IS skrev sine poster. Konsekvensene var:

  • Tung belastning (med 85 % av forespørslene blir lest).
  • Basen vokste. På grunn av dette ble kostnader og støtte et problem.
  • Enkeltpunkt for feil. Hvis en applikasjon som skrev til databasen plutselig begynte å gjøre det mer aktivt, så følte andre applikasjoner virkningen.
  • Ineffektivitet i lagring og spørringer. Ofte ble dataene lagret i en struktur som var praktisk for noen scenarier, men ikke for andre. Indekser fremskynder noen operasjoner, men kan bremse andre.
  • Noen av problemene ble løst ved å raskt lage cacher og lese-replikaer til databaser (dette vil bli diskutert i en egen artikkel), men de tillot oss bare å vinne tid og løste ikke fundamentalt problemet.

Problemet var tilstedeværelsen av selve monolitten. Konsekvensene var:

  • Unike og sjeldne utgivelser.
  • Vanskeligheten ligger i samarbeidsutvikling av et stort antall mennesker.
  • Manglende evne til å introdusere nye teknologier, nye rammer og biblioteker.

Problemer med basen og monolitten har blitt beskrevet mange ganger, for eksempel i sammenheng med krasj tidlig i 2018 (Vær som Munch, eller noen få ord om teknisk gjeld, Dagen Dodo IS stoppet. Asynkront skript и Historien om Dodo-fuglen fra Phoenix-familien. Det store fallet til Dodo ER), så jeg vil ikke dvele for mye. La meg bare si at vi ønsket å gi mer fleksibilitet ved utvikling av tjenester. For det første gjaldt dette de som var mest lastet og root i hele systemet - Auth og Tracker.

Back Office Path: Separate baser og buss

Kapittel Navigering

  1. Opplegg av monolitten 2016
  2. Vi begynner å losse monolitten: separasjon av Auth og Tracker
  3. Hva gjør Auth?
  4. Hvor kommer lastene fra?
  5. Loser Auth
  6. Hva gjør Tracker?
  7. Hvor kommer lastene fra?
  8. Lossing av Tracker

Opplegg av monolitten 2016

Her er hovedblokkene til 2016 Dodo IS-monolitten, og rett nedenfor er en oversikt over hovedoppgavene deres.
Historien om Dodo IS-arkitekturen: Back Office Path
Levering kasse. Regnskap for kurerer, utstede bestillinger til kurerer.
Kontaktsenter. Ta imot bestillinger gjennom operatøren.
Side. Våre nettsteder (dodopizza.ru, dodopizza.co.uk, dodopizza.by, etc.).
Auth. Autorisasjons- og autentiseringstjeneste for backoffice.
Трекер. Bestillingssporer for kjøkken. Tjeneste for merking av beredskapsstatuser ved utarbeidelse av bestilling.
Restaurant kasse. Ta bestillinger i en restaurant, kassegrensesnitt.
Eksport. Opplasting av rapporter i 1C for regnskap.
Varsler og fakturaer. Talekommandoer på kjøkkenet (for eksempel «Ny pizza har kommet») + utskrift av fakturaer for bud.
Skiftleder. Grensesnitt for arbeidet til en skiftleder: liste over bestillinger, produktivitetsdiagrammer, bringe ansatte til skift.
Kontorsjef. Grensesnitt for arbeidet til franchisetakere og ledere: mottak av ansatte, rapporter om arbeidet til pizzeriaen.
Restaurantbord. Viser menyer på TV-er i pizzeriaer.
Admin. Innstillinger for en bestemt pizzeria: meny, priser, regnskap, kampanjekoder, kampanjer, bannere for siden, etc.
Ansatt personlig konto. Ansattes arbeidsplaner, informasjon om ansatte.
Kjøkken Motivasjonstavle. En egen skjerm som henger på kjøkkenet og viser hastigheten til pizzakokerne.
Kommunikasjon. Sender sms og e-post.
FileStorage. Egen tjeneste for mottak og utstedelse av statiske filer.

De første forsøkene på å løse problemer hjalp oss, men de var bare et midlertidig pusterom. De ble ikke systemløsninger, så det var klart at noe måtte gjøres med basene. Del for eksempel den generelle databasen i flere mer spesialiserte.

Vi begynner å losse monolitten: separasjon av Auth og Tracker

De viktigste tjenestene som deretter skrev og leste fra databasen mer enn andre:

  1. Auth. Autorisasjons- og autentiseringstjeneste for backoffice.
  2. Tracker. Bestillingssporer for kjøkken. Tjeneste for merking av beredskapsstatuser ved utarbeidelse av bestilling.

Hva gjør Auth?

Auth er en tjeneste der brukere logger inn på backoffice (det er en egen uavhengig pålogging på klientsiden). Det er også referert i forespørselen for å sikre at de riktige tilgangsrettighetene er til stede og at disse rettighetene ikke er endret siden siste pålogging. Enheter kommer inn i pizzeriaer gjennom den.

For eksempel ønsker vi å åpne en skjerm med status for gjennomførte bestillinger på TV-en som henger i hallen. Deretter åpner vi auth.dodopizza.ru, velg "Logg på som enhet", en kode vises som kan skrives inn på en spesiell side på skiftlederens datamaskin, som indikerer typen enhet (enhet). Selve TV-en vil gå til ønsket grensesnitt til pizzeriaen og begynne å vise navnene på kundene hvis bestillinger er klare.

Historien om Dodo IS-arkitekturen: Back Office Path

Hvor kommer lastene fra?

Hver innlogget backoffice-bruker går til databasen for hver forespørsel, til brukertabellen, trekker ut brukeren derfra gjennom en sql-spørring og sjekker om han har nødvendig tilgang og rettigheter til denne siden.

Hver av enhetene gjør det samme bare med enhetstabellen, og sjekker dens rolle og tilganger. Et stort antall forespørsler til hoveddatabasen fører til lasting og sløsing med generelle databaseressurser på disse operasjonene.

Loser Auth

Auth har et isolert domene, det vil si at data om brukere, pålogginger eller enheter kommer inn i tjenesten (for øyeblikket fremtidig) og forblir der. Hvis noen trenger dem, vil han gå til denne tjenesten for data.

VAR. Arbeidsflyten var i utgangspunktet slik:

Historien om Dodo IS-arkitekturen: Back Office Path

Jeg vil gjerne forklare litt hvordan det fungerte:

  1. En ekstern forespørsel kommer til backend (Asp.Net MVC der), og bringer med seg en session-cookie, som brukes til å hente sesjonsdata fra Redis(1). Den inneholder enten informasjon om tilganger, og da er tilgangen til kontrolleren åpen (3,4), eller ikke.
  2. Hvis det ikke er tilgang, må du gå gjennom autorisasjonsprosedyren. Her vises den for enkelhets skyld som en del av banen i samme attributt, selv om dette er en overgang til påloggingssiden. Ved et positivt scenario vil vi motta en korrekt fylt økt og gå til Backoffice Controller.
  3. Hvis det er data, må du sjekke det for relevans i brukerdatabasen. Har rollen hans endret seg, bør han ikke få komme inn på siden nå? I dette tilfellet, etter å ha mottatt økten (1), må du gå direkte til databasen og sjekke brukerens tilgang ved å bruke autentiseringslogikklaget (2). Deretter går du enten til påloggingssiden eller går til kontrolleren. Dette er et enkelt system, men ikke helt standard.
  4. Hvis alle prosedyrer er fullført, hopper vi videre i logikken i kontrollere og metoder.

Brukerdata er atskilt fra alle andre data, de lagres i en egen medlemstabell, funksjoner fra AuthService-logikklaget kan godt bli API-metoder. Grensene for domenet er definert ganske klart: brukere, deres roller, tilgangsdata, utstedelse og tilbakekall av tilgang. Alt ser ut til å kunne flyttes til en egen tjeneste.

BLE TIL. Det var det de gjorde:

Historien om Dodo IS-arkitekturen: Back Office Path

Denne tilnærmingen har en rekke problemer. Å kalle en metode inne i en prosess er for eksempel ikke det samme som å ringe en ekstern tjeneste via http. Latens, pålitelighet, støttebarhet og åpenhet av operasjonen er helt annerledes. Andrey Morevsky snakket mer detaljert om akkurat disse problemene i sin rapport "50 nyanser av mikrotjenester".

Autentiseringstjenesten og med den enhetstjenesten brukes til backoffice, det vil si for tjenester og grensesnitt som brukes i produksjon. Autentisering for klienttjenester (som et nettsted eller en mobilapplikasjon) skjer separat uten å bruke Auth. Separasjonen tok omtrent et år, og nå jobber vi igjen med dette temaet, og overfører systemet til nye autentiseringstjenester (med standardprotokoller).

Hvorfor tok separasjonen så lang tid?
Det var mange problemer underveis som bremset oss:

  1. Vi ønsket å overføre data om brukere, enheter og autentisering fra landdatabaser til én. For å gjøre dette måtte vi overføre alle tabeller og bruk fra int-identifikatoren til den globale UUId-identifikatoren (vi har nylig omarbeidet denne koden Roman Bukin "Uuid - den store historien om en liten struktur" og åpen kildekode-prosjekt Primitiver). Lagring av brukerdata (siden dette er personlig informasjon) har sine begrensninger og for noen land er det nødvendig å lagre dem separat. Men det må være en global bruker-ID.
  2. Mange tabeller i databasen har revisjonsinformasjon om brukeren som utførte operasjonen. Dette krevde en ekstra mekanisme for å sikre konsistens.
  3. Etter opprettelsen av API-tjenester var det en lang og gradvis overgangsperiode til et annet system. Brytere måtte skje sømløst for brukerne og krevde manuelt arbeid.

Opplegg for registrering av en enhet i en pizzeria:

Historien om Dodo IS-arkitekturen: Back Office Path

Generell arkitektur etter separering av Auth- og Devices-tjenesten:

Historien om Dodo IS-arkitekturen: Back Office Path

Note. For 2020 jobber vi med en ny versjon av Auth, som er basert på autorisasjonsstandarden OAuth 2.0. Denne standarden er ganske kompleks, men nyttig for å utvikle en ende-til-ende autentiseringstjeneste. I artikkelen "Finesser av autorisasjonen: oversikt over OAuth 2.0-teknologi» vi Alexey Chernyaev prøvde å snakke om standarden så enkelt og tydelig som mulig, slik at du sparer tid på å studere den.

Hva gjør Tracker?

Nå om den andre av de lastede tjenestene. Trackeren har en dobbel rolle:

  • På den ene siden er oppgaven å vise ansatte på kjøkkenet hvilke bestillinger som er i gang, hvilke produkter som må tilberedes nå.
  • Digitaliser derimot alle prosesser på kjøkkenet.

Historien om Dodo IS-arkitekturen: Back Office Path

Når et nytt produkt (for eksempel pizza) dukker opp i en bestilling, går det til "Rolling"-sporingsstasjonen. På denne stasjonen er det en pizzamaker som tar en bolle i ønsket størrelse og ruller den ut, hvoretter han merker på tracker-tabletten at han har fullført oppgaven og sender den utkjevlede deigbunnen til neste stasjon - "Fyling" .

Der topper neste pizzamaker pizzaen, markerer så på nettbrettet at han har fullført oppgaven og setter pizzaen i ovnen (dette er også en egen stasjon som må merkes på nettbrettet). Et slikt system var til stede helt fra begynnelsen i Dodo og helt fra begynnelsen av Dodo IS. Den lar deg spore og digitalisere alle operasjoner. I tillegg foreslår trackeren hvordan man tilbereder et bestemt produkt, utfører hver type produkt i henhold til sine egne produksjonsskjemaer, lagrer den optimale koketiden for produktet og sporer alle operasjoner på produktet.

Historien om Dodo IS-arkitekturen: Back Office PathSlik ser nettbrettskjermen ut på Raskatka-sporingsstasjonen.

Hvor kommer lastene fra?

Hver pizzeria har omtrent fem nettbrett med en tracker. I 2016 hadde vi mer enn 100 pizzeriaer (og nå er det mer enn 600). Hvert av nettbrettene sender en forespørsel til backend hvert 10. sekund og samler inn data fra bestillingstabellen (lenke til klienten og adresse), bestillingssammensetningen (lenke til produktet og angivelse av mengde) og motivasjonstabellen (den sporer tidspunktet for trykking). Når en pizzaprodusent klikker på et produkt på trackeren, oppdateres postene i alle disse tabellene. Ordretabellen er generell, den inneholder samtidig innsettinger når du aksepterer en bestilling, oppdateringer fra andre deler av systemet, og en rekke avlesninger, for eksempel på en TV som henger i en pizzeria og viser ferdige bestillinger til kundene.

I løpet av perioden med kamp med belastninger, da alt og alle ble bufret og overført til en asynkron kopi av databasen, fortsatte disse operasjonene med trackeren å gå til hoveddatabasen. Det skal ikke være noen etterslep her, dataene må være oppdatert, usynkronisert er uakseptabelt.

Også mangelen på våre egne tabeller og indekser på dem tillot oss ikke å skrive mer spesifikke søk skreddersydd for vår bruk. For eksempel kan det være effektivt for en tracker å ha en indeks for en pizzeria på bestillingstabellen. Vi skraper alltid pizzeriabestillinger fra trackerdatabasen. Samtidig, for å akseptere en bestilling, er det ikke så viktig hvilken pizzeria den faller inn i, det som er viktigere er hvilken klient som har laget denne bestillingen. Dette betyr at det må være en indeks på klienten. Det er heller ikke nødvendig for trackeren å lagre ID-en til den trykte kvitteringen eller bonuskampanjene knyttet til bestillingen i bestillingstabellen. Vår sporingstjeneste er ikke interessert i denne informasjonen. I en felles monolittisk database kan tabeller bare være et kompromiss mellom alle brukere. Dette var et av de opprinnelige problemene.

VAR. Opprinnelig var arkitekturen slik:

Historien om Dodo IS-arkitekturen: Back Office Path

Selv etter å ha blitt separert i separate prosesser, forble det meste av kodebasen felles for forskjellige tjenester. Alt under kontrollerene ble samlet og bodde i ett depot. Vanlige metoder for tjenester, depoter og en felles database som inneholder vanlige tabeller ble brukt.

Lossing av Tracker

Hovedproblemet med trackeren er at dataene må synkroniseres mellom ulike databaser. Dette er også hovedforskjellen fra inndelingen av Auth-tjenesten; rekkefølgen og dens status kan endres og bør vises i ulike tjenester.

Vi aksepterer bestillinger i Restaurant Checkout (dette er en tjeneste), den lagres i databasen i "Accepted" status. Etter det skal den gå til trackeren, hvor den vil endre status flere ganger: fra "Kjøkken" til "Packet". I dette tilfellet kan noen ytre påvirkninger fra kassereren eller Shift Manager-grensesnittet oppstå med bestillingen. Jeg vil gi ordrestatusene med beskrivelsene i tabellen:

Historien om Dodo IS-arkitekturen: Back Office Path
Ordrestatusendringen ser slik ut:

Historien om Dodo IS-arkitekturen: Back Office Path

Statuser endres mellom ulike systemer. Og her er ikke trackeren det endelige systemet som dataene er låst i. Vi har sett flere mulige tilnærminger for separasjon i et slikt tilfelle:

  1. Vi konsentrerer alle ordrehandlinger i én tjeneste. I vårt tilfelle krever dette alternativet for mye service for å behandle bestillingen. Hvis vi hadde stoppet der, ville vi endt opp med en annen monolitt. Vi ville ikke ha løst problemene.
  2. Ett system ringer til et annet. Det andre alternativet er mer interessant. Men med det er kjeder av samtaler mulig (kaskadefeil), er tilkoblingen til komponentene høyere, og det er vanskeligere å administrere.
  3. Vi arrangerer arrangementer, og hver tjeneste utveksler med hverandre gjennom disse arrangementene. Som et resultat ble det tredje alternativet valgt, i henhold til hvilket alle tjenester begynner å utveksle hendelser med hverandre.

Det at vi valgte det tredje alternativet gjorde at trackeren ville ha sin egen database, og for hver endring i rekkefølgen ville den sende en hendelse om dette, som andre tjenester ville abonnere på og som også ble inkludert i masterdatabasen. For å gjøre dette trengte vi en tjeneste som ville sikre levering av meldinger mellom tjenestene.

På det tidspunktet hadde vi allerede RabbitMQ i stabelen, derav den endelige beslutningen om å bruke den som meldingsmegler. Diagrammet viser overgangen til en bestilling fra Restaurant-kassereren gjennom Trackeren, hvor den endrer status og visning i lederens ordregrensesnitt. BLE TIL:

Historien om Dodo IS-arkitekturen: Back Office Path

Bestill bane trinn for trinn
Ordrebanen begynner ved en av ordrekildetjenestene. Her er restaurantkassen:

  1. Bestillingen er helt klar i kassen, og det er på tide å sende den til trackeren. Hendelsen som trackeren abonnerer på kastes.
  2. Trackeren, som aksepterer en bestilling, lagrer den i sin egen database, gjør hendelsen "Order Accepted by Tracker" og sender den til RMQ.
  3. Flere behandlere er allerede abonnert på den tilpassede hendelsesbussen. For oss er den som synkroniserer med den monolittiske databasen viktig.
  4. Behandleren mottar hendelsen, velger fra den dataene som er viktige for den: i vårt tilfelle er dette ordrestatusen "Accepted by Tracker" og oppdaterer ordreenheten i hoveddatabasen.

Hvis noen trenger en ordre spesifikt fra den monolittiske ordretabellen, kan de også lese den derfra. Dette er for eksempel hva ordregrensesnittet i Shift Manager trenger:

Historien om Dodo IS-arkitekturen: Back Office Path

Alle andre tjenester kan også abonnere på bestillingshendelser fra trackeren for å bruke dem selv.

Hvis en ordre etter en tid tas i produksjon, endres først statusen i databasen (Tracker-databasen), og deretter genereres «OrderInWork»-hendelsen umiddelbart. Den kommer også inn i RMQ, hvorfra den synkroniseres i en monolittisk database og leveres til andre tjenester. Det kan være forskjellige problemer langs denne veien; flere detaljer om dem kan finnes i Zhenya Peshkovs rapport om implementeringsdetaljene til Eventual Consistency in Tracker.

Endelig arkitektur etter endringer i Auth og Tracker

Historien om Dodo IS-arkitekturen: Back Office Path

Å oppsummere: I utgangspunktet hadde jeg ideen om å pakke den ni år lange historien til Dodo IS-systemet i én artikkel. Jeg ønsket å raskt og enkelt snakke om stadiene av evolusjon. Men etter å ha satt meg ned for å studere materialet, innså jeg at alt er mye mer komplekst og interessant enn det ser ut til.

Etter å ha reflektert over fordelene (eller mangelen på det) med slikt materiale, kom jeg til den konklusjon at kontinuerlig utvikling er umulig uten fullverdige kronikker av hendelser, detaljerte tilbakeblikk og analyser av tidligere beslutninger.

Jeg håper du syntes det var nyttig og interessant å lære om reisen vår. Nå står jeg overfor et valg om hvilken del av Dodo IS-systemet jeg skal beskrive i neste artikkel: skriv i kommentarfeltet eller stem.

Kun registrerte brukere kan delta i undersøkelsen. Logg inn, vær så snill.

Hvilken del av Dodo IS vil du lære om i neste artikkel?

  • 24,1%Tidlig monolitt i Dodo IS (2011-2015)14

  • 24,1%De første problemene og deres løsninger (2015-2016)14

  • 20,7%Bane til byggherredelen: fasade over basen (2016-2017)12

  • 36,2%Historien om ekte mikrotjenester (2018-2019)21

  • 44,8%Fullført kutting av monolitten og stabilisering av arkitekturen26

  • 29,3%Om videre planer for utvikling av systemet17

  • 19,0%Jeg vil ikke vite noe om Dodo IS11

58 brukere stemte. 6 brukere avsto.

Kilde: www.habr.com

Legg til en kommentar