Hej alle! Vi har gode nyheder, OTUS lancerer kurset igen til juni
Hvis du er stødt på hele denne mikroserviceting uden nogen kontekst, ville du blive tilgivet for at synes, det er lidt mærkeligt. At opdele en applikation i fragmenter forbundet af et netværk betyder nødvendigvis at tilføje komplekse fejltolerancetilstande til det resulterende distribuerede system.
Selvom denne tilgang involverer at opdele det i mange uafhængige tjenester, er slutmålet meget mere end blot at få disse tjenester til at køre på forskellige maskiner. Vi taler her om interaktion med omverdenen, som også er fordelt i sin essens. Ikke i teknisk forstand, men snarere i betydningen af et økosystem, der består af mange mennesker, teams, programmer, og hver af disse dele skal på en eller anden måde gøre sit arbejde.
Virksomheder er for eksempel en samling af distribuerede systemer, der tilsammen bidrager til opnåelsen af et eller andet mål. Vi har ignoreret denne kendsgerning i årtier og forsøgt at opnå ensretning ved at FTP-filer eller bruge virksomhedsintegrationsværktøjer, mens vi fokuserer på vores egne isolerede mål. Men med fremkomsten af tjenester ændrede alt sig. Tjenester har hjulpet os med at se ud over horisonten og se en verden af indbyrdes afhængige programmer, der arbejder sammen. Men for at kunne arbejde med succes er det nødvendigt at genkende og designe to fundamentalt forskellige verdener: den ydre verden, hvor vi lever i et økosystem af mange andre tjenester, og vores personlige, indre verden, hvor vi hersker alene.
Denne distribuerede verden er anderledes end den, vi voksede op i og er vant til. Principperne for at konstruere traditionel monolitisk arkitektur tåler ikke kritik. Så at få disse systemer rigtige handler om mere end at skabe et cool whiteboard-diagram eller et sejt proof of concept. Pointen er at sikre, at et sådant system fungerer med succes over en lang periode. Heldigvis har tjenesterne eksisteret i et stykke tid, selvom de ser anderledes ud.
Så i dag skal vi se på, hvordan reglerne har ændret sig, hvorfor vi skal gentænke den måde, vi griber tjenester til og de data, de videregiver til hinanden, og hvorfor vi skal bruge helt andre værktøjer til at gøre det.
Indkapsling vil ikke altid være din ven
Mikrotjenester kan fungere uafhængigt af hinanden. Det er denne egenskab, der giver dem den største værdi. Den samme egenskab tillader tjenester at skalere og vokse. Ikke så meget i betydningen skalering til kvadrillioner af brugere eller petabytes af data (selvom de også kan hjælpe der), men i betydningen skalering i form af mennesker, efterhånden som teams og organisationer vokser kontinuerligt.
Uafhængighed er dog et tveægget sværd. Det vil sige, at selve tjenesten kan køre nemt og naturligt. Men hvis en funktion implementeres i en tjeneste, der kræver brug af en anden tjeneste, så ender vi med at skulle lave ændringer på begge tjenester næsten samtidigt. I en monolit er dette nemt at gøre, du laver bare en ændring og sender den til frigivelse, men i tilfælde af synkronisering af uafhængige tjenester vil der være flere problemer. Koordinering mellem hold og frigivelsescyklusser ødelægger smidigheden.
Som en del af standardtilgangen forsøger de simpelthen at undgå irriterende ende-til-ende-ændringer, der tydeligt opdeler funktionalitet mellem tjenester. Single sign-on service kan være et godt eksempel her. Den har en klart defineret rolle, der adskiller den fra andre tjenester. Denne klare adskillelse betyder, at i en verden med hurtigt skiftende krav til tjenesterne omkring den, er det usandsynligt, at single sign-on-tjenesten ændrer sig. Det eksisterer i en strengt begrænset kontekst.
Problemet er, at i den virkelige verden kan forretningsservice ikke opretholde den samme rene adskillelse af roller hele tiden. For eksempel arbejder de samme erhvervsservices i højere grad med data, der kommer fra andre lignende tjenester. Hvis du er involveret i online detailhandel, vil behandling af ordreflow, produktkatalog eller brugeroplysninger blive et krav for mange af dine tjenester. Hver af tjenesterne skal have adgang til disse data for at kunne fungere.
De fleste forretningstjenester deler den samme datastrøm, så deres arbejde er uvægerligt sammenflettet.
Dermed kommer vi til et vigtigt punkt, der er værd at tale om. Selvom tjenester fungerer godt for infrastrukturkomponenter, der stort set fungerer isoleret, ender de fleste forretningstjenester med at blive flettet meget tættere sammen.
Data dikotomi
Serviceorienterede tilgange findes måske allerede, men de mangler stadig indsigt i, hvordan man deler store mængder data mellem tjenester.
Hovedproblemet er, at data og tjenester er uadskillelige. På den ene side tilskynder indkapsling os til at skjule data, så tjenester kan adskilles fra hinanden og lette deres vækst og yderligere ændringer. På den anden side skal vi frit kunne opdele og erobre delt data, ligesom alle andre data. Pointen er at kunne begynde at arbejde med det samme, lige så frit som i ethvert andet informationssystem.
Informationssystemer har dog ikke meget med indkapsling at gøre. Faktisk er det stik modsat. Databaser gør alt, hvad de kan for at give adgang til de data, de gemmer. De kommer med en kraftfuld deklarativ grænseflade, der giver dig mulighed for at ændre dataene efter behov. En sådan funktionalitet er vigtig på det foreløbige forskningsstadium, men ikke for at håndtere den voksende kompleksitet af en tjeneste i konstant udvikling.
Og her opstår et dilemma. Modsigelse. Modsætning. Informationssystemer handler jo om at levere data, og tjenester handler om at gemme sig.
Disse to kræfter er fundamentale. De understøtter meget af vores arbejde og kæmper konstant for ekspertise i de systemer, vi bygger.
Efterhånden som servicesystemer vokser og udvikler sig, ser vi konsekvenserne af datadikotomi på mange måder. Enten vil servicegrænsefladen vokse til at give et stadigt bredere udvalg af funktionalitet og begynde at ligne en meget fancy hjemmelavet database, eller også vil vi blive frustrerede og implementere en eller anden måde at hente eller flytte i massevis af hele datasæt fra service til service.
Til gengæld vil det at skabe noget, der ligner en fancy hjemmelavet database, føre til en lang række problemer. Vi vil ikke komme nærmere ind på, hvorfor det er farligt delt database, lad os bare sige, at det repræsenterer betydelige omkostningskrævende teknik og operationelle
Hvad værre er, er, at datamængder forstørrer servicegrænseproblemer. Jo mere delte data der ligger i en tjeneste, jo mere kompleks bliver grænsefladen, og jo sværere vil det være at kombinere datasæt, der kommer fra forskellige tjenester.
Den alternative tilgang med at udtrække og flytte hele datasæt har også sine problemer. En almindelig tilgang til dette spørgsmål ligner blot at hente og gemme hele datasættet og derefter gemme det lokalt i hver forbrugende service.
Problemet er, at forskellige tjenester fortolker de data, de bruger, forskelligt. Disse data er altid ved hånden. De modificeres og behandles lokalt. Ret hurtigt holder de op med at have noget til fælles med dataene i kilden.
Jo mere foranderlige kopierne er, jo mere vil dataene variere over tid.
For at gøre ondt værre er sådanne data svære at rette i retrospekt (
For at finde en løsning på dette problem er vi nødt til at tænke anderledes om delte data. De skal blive førsteklasses objekter i de arkitekturer, vi bygger.
Problemet er, at ingen af tilgangene er relevante i dag, da hverken servicegrænseflader, beskedudveksling eller den delte database tilbyder en god løsning til at arbejde med eksterne data. Servicegrænseflader er dårligt egnede til dataudveksling i enhver skala. Beskeder flytter data, men gemmer ikke deres historie, så data bliver beskadiget over tid. Delte databaser fokuserer for meget på ét punkt, hvilket holder fremskridt tilbage. Vi hænger uundgåeligt fast i en cyklus af datafejl:
Cyklus af datafejl
Strømme: en decentral tilgang til data og tjenester
Ideelt set er vi nødt til at ændre den måde, tjenester fungerer på med delte data. På dette tidspunkt står begge tilgange over for den førnævnte dikotomi, da der ikke er noget magisk støv, der kan drysses på det for at få det til at forsvinde. Vi kan dog genoverveje problemet og nå frem til et kompromis.
Dette kompromis indebærer en vis grad af centralisering. Vi kan bruge den distribuerede logmekanisme, fordi den giver pålidelige, skalerbare streams. Vi ønsker nu, at tjenester skal kunne tilslutte sig og operere på disse delte tråde, men vi ønsker at undgå komplekse centraliserede gudstjenester, der udfører denne behandling. Derfor er den bedste mulighed at indbygge strømbehandling i hver forbrugertjeneste. På denne måde vil tjenester være i stand til at kombinere datasæt fra forskellige kilder og arbejde med dem, som de har brug for.
En måde at opnå denne tilgang på er ved at bruge en streamingplatform. Der er mange muligheder, men i dag vil vi se på Kafka, da brugen af dens Stateful Stream Processing giver os mulighed for effektivt at løse det præsenterede problem.
Ved at bruge en distribueret logningsmekanisme kan vi følge den betrampede vej og bruge beskeder til at arbejde med
Hvis en mægler er ansvarlig for distribueret logning i stedet for et traditionelt meddelelsessystem, kan du drage fordel af yderligere funktioner. Transporten kan skaleres lineært næsten lige så godt som et distribueret filsystem. Data kan lagres i logs i ret lang tid, så vi får ikke kun beskedudveksling, men også informationslagring. Skalerbar lagring uden frygt for foranderlig delt tilstand.
Du kan derefter bruge stateful stream-behandling til at tilføje deklarative databaseværktøjer til forbrugende tjenester. Dette er en meget vigtig idé. Mens dataene lagres i delte streams, som alle tjenester kan få adgang til, er den aggregering og behandling, som tjenesten udfører, privat. De befinder sig isoleret inden for en strengt begrænset kontekst.
Eliminer data dikotomi ved at adskille den uforanderlige tilstandsstrøm. Tilføj derefter denne funktionalitet til hver tjeneste ved hjælp af Stateful Stream Processing.
Så hvis din service skal fungere med ordrer, et produktkatalog, et lager, vil den have fuld adgang: Kun du bestemmer, hvilke data der skal kombineres, hvor de skal behandles, og hvordan de skal ændre sig over tid. På trods af at data er delt, er arbejdet med det fuldstændig decentraliseret. Det er produceret inden for hver service, i en verden, hvor alt foregår efter dine regler.
Del data uden at gå på kompromis med dets integritet. Indkapsl funktionen, ikke kilden, i enhver tjeneste, der har brug for den.
Det sker, at data skal flyttes i massevis. Nogle gange kræver en tjeneste et lokalt historisk datasæt i den valgte databasemotor. Tricket er, at du kan garantere, at en kopi om nødvendigt kan gendannes fra kilden ved at få adgang til den distribuerede logningsmekanisme. Connectors i Kafka gør et godt stykke arbejde med dette.
Så den tilgang, der diskuteres i dag, har flere fordele:
- Data bruges i form af fælles streams, som kan lagres i logs i lang tid, og mekanismen til at arbejde med fælles data er fastkablet i hver enkelt kontekst, hvilket gør det muligt for tjenesterne at arbejde nemt og hurtigt. På denne måde kan dataenes dikotomi afbalanceres.
- Data, der kommer fra forskellige tjenester, kan nemt kombineres til sæt. Dette forenkler interaktion med delte data og eliminerer behovet for at vedligeholde lokale datasæt i databasen.
- Stateful Stream Processing cacher kun data, og kilden til sandhed forbliver de generelle logfiler, så problemet med datakorruption over tid er ikke så akut.
- I deres kerne er tjenester datadrevet, hvilket betyder, at på trods af de stadigt stigende mængder af data, kan tjenester stadig reagere hurtigt på forretningsbegivenheder.
- Skalerbarhedsproblemer falder på mægleren, ikke tjenesterne. Dette reducerer kompleksiteten af skrivetjenester markant, da der ikke er behov for at tænke på skalerbarhed.
- Tilføjelse af nye tjenester kræver ikke ændring af gamle, så det bliver nemmere at forbinde nye tjenester.
Som du kan se, er dette mere end bare HVILE. Vi har modtaget et sæt værktøjer, der giver dig mulighed for at arbejde med delt data på en decentral måde.
Ikke alle aspekter blev dækket i dagens artikel. Vi mangler stadig at finde ud af, hvordan vi balancerer mellem anmodnings-svar-paradigmet og det begivenhedsdrevne paradigme. Men vi tager os af det næste gang. Der er emner, som du skal lære bedre at kende, for eksempel hvorfor Stateful Stream Processing er så godt. Vi vil tale om dette i den tredje artikel. Og der er andre kraftfulde konstruktioner, som vi kan drage fordel af, hvis vi tyer til dem, f.eks.
Men for nu skal du bare huske dette: datadikotomien er en kraft, vi står over for, når vi bygger forretningstjenester. Og det skal vi huske. Tricket er at vende alt på hovedet og begynde at behandle delte data som førsteklasses objekter. Stateful Stream Processing giver et unikt kompromis for dette. Det undgår centraliserede "Gudskomponenter", der holder fremskridt tilbage. Desuden sikrer det smidigheden, skalerbarheden og robustheden af datastreaming-pipelines og føjer dem til hver service. Derfor kan vi fokusere på den generelle strøm af bevidsthed, som enhver tjeneste kan forbinde til og arbejde med sine data. Dette gør tjenester mere skalerbare, udskiftelige og autonome. Så de vil ikke kun se godt ud på whiteboards og hypotesetests, men de vil også fungere og udvikle sig i årtier.
Kilde: www.habr.com