Efter ti år med mikrotjenester gør chefudvikler status: Småt er godt, men ...

Lille og elegant. Illustration: JiriHrebicek | Bigstock
Meget er blevet bedre og forstået i højere grad end tidligere, når det handler om mikrotjenester. Men 'fysikkens love' glemmes stadig, og 'sagaer' kan give bedre overblik end log-filer, mener udvikler.

På Øredev-konferencen, der løb af stablen i Malmø i sidste uge, gav Tomer Gabel et tilbageblik på de seneste fem-ti år med mikrotjenester. Han er ledende udvikler i den ombruste internationale ejendomsmægler-virksomhed Wework.

Mikrotjenester er dagens finkornede udgave af tidligere tiders tjenesteorienterede arkitektur (SOA), der har brudt fortidens systemer ned i mindre dele, som er til at håndtere.

Det handler i bund og grund om skalering, siger Tomer Gabel. Det er nemmere at optimere små systemer end ét stort monolitisk serversystem. Det betyder også, at et nedbrud et sted ikke nødvendigvis forplanter sig til resten af systemet.

Som eksempel nævner Tomer Gabel et udfald i et Netflix-system, der anbefaler indhold til tjenestens seere.

Den gik ned, men brugerne kunne stadig se deres yndlingsserier og benytte tjenestens andre funktioner.

I gammeldags, monolitiske serversystemer er det ikke helt lige så sikkert, at et nedbrud et sted ikke lægger andre funktioner ned.

Der er andre fordele ved mikrotjenester. Man kan bruge flere sprog og afviklingsmiljøer side om side, og måske, siger Tomer Gabel, er systemerne også nemmere at teste.

Det handler om mennesker

Men det er nu slet ikke disse grunde, der ifølge Tomer Gabel gør mikrotjenester til udvikleres favorit-arkitektur. I virkeligheden handler det nemlig om at skalere organisationen og ikke teknologien.

Det er ganske simpelt for svært at have ét kæmpe udviklingshold, hvor alle arbejder med én monolitisk applikation og datakilde. I stedet bør man have mange små teams, der har hver sit produkt og hver sine målsætninger, og det er meget nemmere at have med at gøre, mener Tomer Gabel.

Det er problemer med mennesker, og ikke maskiner, som mikrotjenester løser, mener Tomer Gabel fra firmaet Wework. Illustration: Tania Andersen

Men ikke alt er fryd og gammen i mikrotjenesternes verden. Nye ideer giver nye problemer, og gamle kendinge stikker hovedet frem igen.

Over tid bliver tjenesterne og de produkter, de leverer, afhængige af hinanden. Det samme gælder software-teams. Det giver ‘synkroniseringsomkostninger,’ som Tomer Gabel udtrykker det.

De vigtigste målepunkter bliver alle negativt påvirket af synkronisering, hvor en lang række uafhængige tjenester og udvikler-hold skal deltage i den samme dans.

Den gode nyhed er, at mikrotjeneste-arkitektur er velegnet til at ordne disse problemer. Det, vi ønsker, siger Tomer Gabel, er minimalt besvær med synkronisering og maksimal uafhængighed mellem systemerne.

Det simple budskab er, at ‘småt er godt’. Små systemer kan overskues af mennesker. Det udmønter sig i små grænseflader mellem tjenesterne. API’erne skal have den mindst mulige flade.

Undgå bøvl med mikrotjenester

Tomer Gabel har et par gode råd i den anledning. Del aldrig datakilder mellem tjenester, lyder formaningen. En delt database betyder, at SQL er en grænseflade – og en meget stor og uhåndterlig en af slagsen.

Flere stakke – platforme og sprog – er ikke nødvendigt, og ikke ønskværdigt for din virksomhed. Et lille antal stakke minimerer flaskehalse i forhold til produktion af kode og funktionalitet, når udviklerne har de samme færdigheder.

Konkret mener Tomer Gabel, at der ikke er behov for mere end to eller tre stakke i en større virksomhed.

Han har researchet lidt på sagen og er kommet frem til, at Google scorer højest med seks eller syv stakke i eget hus, mens de fleste andre store it-virksomheder ligger på de førnævnte to-tre stykker.

En anden indsigt, som ifølge Tomer Gabel stammer fra den amerikanske datalog Melvin Conway, lyder således: Måden, som en organisation snakker sammen på, har en tendens til at afspejle sig i den struktur, som organisationens software-systemer benytter.

Det kaldes ‘Conways lov’. Og det betyder, at det er vigtigt at have organisationens struktur in mente, da den har betydning for, hvordan tjenesterne og deres relationer udkrystalliseres.

Faretegn er som nævnt datakilder, der deles af flere tjenester, samt ét system, der har flere teams som ejere. Her lyder det barske råd fra Tomer Gabel, at man skal omstrukturere organisationen, hvis man ender i disse situationer.

De øvrige anbefalinger er gamle kendinge, som Tomer Gabel også påpeger: Gå efter mange små og hyppige releases, få devops-dyderne op under neglene, og automatisering er nøglen til et gladere udvikler-liv.

Det, vi ikke lærte

Der er altså høstet mange konstruktive erfaringer om mikrotjenester i de seneste 10 års tid. Men Tomer Gabel spørger retorisk: Hvad har vi ikke lært?

Her peger han på, hvad han kalder for ‘fysikkens love.’ Han refererer til to dataloger, Leslie Lamport og Eric Brewer, der begge har forsket i distribuerede systemer.

Det er det forhold, der karakteriserer mikrotjenesters natur. Nøglen til bedre forståelse af problemet er begrebet ‘concurrency’ – samtidig afvikling af processer. Ellers får man inkonsistens i systemer, der arbejder side om side.

Distribuerede systemer er nemlig svære at tænke på. Og dagens værktøjer og metoder halter bagefter, lyder synspunktet. Værktøjerne bliver dog bedre, og det handler eksempelvis om ‘tracing’, metrikker og aggregering af log-filer.

Men det er ikke nok. Man skal vide, hvad der skal logges, optælles, overvåges, og hvordan det hele giver mening. Det er så at sige systemets KPI’er – key performance indicators, som det hedder på moderne management-sprog – der skal fastsættes.

Løsningen er events

Vi skal altså minimere synkronisering og maksimere uafhængighed. Det, som udviklere og organisationer kæmper med, er sikkerhed, skalering og ‘observability’ – evnen til på en koncis måde at vide, hvad systemet faktisk foretager sig.

Løsningen er klassikere som køer og ‘busser’, men med events – begivenheder – som det centrale element.

Her er idealet, som Tomer Gabel ser det, en model, hvor events udsendes og konsumeres via en bus eller kø, som alle systemerne er koblet til.

Events kan gemmes i den rækkefølge, de opstår, og ligesom i finans-it, hvor en saldo opsummeres ved at sammenregne en sekvens af poster, giver en sekvens af events muligheden for at observere og foretage revision på det slutresultat, som systemet ender med.

I distribuerede systemer er ‘eventual consistency’ (det forhold, at et systems samlede tilstand ikke er kendt på alle tidspunkter) bare et af livets fakta, som er uundgåeligt, hvis man også skal have ‘high availability’ – at mange brugere skal tilgå systemet og foretage transaktioner samtidig.

Her er et revisionsspor vigtigt, hvis fejl skal findes og rettes.

Tomer Gabel mener, at et godt programmeringsmønster i denne sammenhæng er en ‘saga’, der repræsenterer en enkelt forretningsproces på højt niveau; som for eksempel en bruger, der booker en flyrejse.

Processen består af flere kald på et lavt niveau, der fører til, at hver tjeneste opdaterer data. Hvert kald i processen kan udføre en handling, når anmodningen mislykkes, eller sagaen afbrydes.

Sæt dig ind i den gældende viden på området, lyder Tomer Gabels afsluttende formaning til den tætpakkede sal i Malmøs messecenter, der kvitterer med klapsalver.

Tænk over dit event-API – det er hårdt arbejde

På Version2’s opfølgende spørgsmål om, hvorledes man kan minimere et API’s grænseflade, hvis alle tjenester skal kunne modtage alle slags events via en bus, uddyber Tomer Gabel:

»Hvis du har brug for at indfange alle slags events, betyder det som regel, at brugsscenarierne er spredt over flere tjenester. Hver tjeneste er i sig selv stadig lille. Når det er sagt, så er svaret på spørgsmålet om, hvordan man minimerer API’ets grænseflade, at der ikke er nogen ‘magic bullet’. Du skal være disciplineret og tænke meget over, hvorledes API’et fremstilles – der er ikke nogen anden måde at gøre det på.«

Man skal overveje, hvad forholdet mellem fordele og ulemper er, og bruge tid på at tænke over, om man virkelig har brug for en given information eller parameter i et kald.

»Og hvad konsekvenserne er ved at tilføje en parameter. Hvis du føjer noget til dit system, bliver det sværere at ændre eller fjerne på et senere tidspunkt. Derfor er det vigtigt at overveje hver enkelt del, som du tilføjer til din grænseflade. Det er hårdt arbejde.«

Det betyder dog ikke, at bindinger mellem forskellige tjenester er noget skidt.

»Bindinger er det, som giver funktionalitet i dine mikrotjenester. Her hjælper events meget. På konsument-siden betyder det, at du kan vælge de data, som du bruger, uden at producent-tjenesten, der fremsender data, ved noget om det. Det er fordelen ved at producere og konsumere events: Konsumenterne er uafhængige og behøver ikke at fortælle producenten, at de aftager data. Det er en af de teknikker, som er mest fordelagtig i forbindelse med at reducere sammenkobling mellem systemer,« slutter Tomer Gabel.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (7)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Morten Bøgh

Ja, det er altid en god ide at observere fysikkens love: tyngdeloven etc. Hvorvidt man skal overholde dem, behøver man ikke overveje, det læres den hårde vej hvis man ignorerer dem.
Referatet ovenfor cirkler rundt og rundt omkring det uløselige problem ved microservices: At services ikke kører i et fælles commit-space, og at der derfor ikke er styr på fx det klassiske bankproblem: Service A trækker 10 kr ud fra konto X, Service B skulle så have sat pengene ind på konto Y, men fejler. Resultatet: Banken vinder 10 kr. Det er 'bare et af livets fakta' ved distribuerede systemer, som det hedder i referatet ovenfor.

Rådet i referatet om for enhver pris at undgå SQL-databaser, fordi det binder services sammen - er grotesk.
I stedet bør man åbenbart køre et kæmpe cirkus af logs for at checke at fejl er sket... Hvad med at erstatte alle disse logs med en veldesignet SQL-database som registrerer systemets hændelser (set i relation til systemets formål). Dels er det meget nemmere at håndtere, dels gør det at fejl kan forebygges (...fælles commit) i stedet for at kompenseres (eller undskyldes) i efterfølgende sagsbehandling.

Det hele afhænger af systemets og komponentens formål. En service som giver gode og dårlige råd om valg af den næste film i Netflix - den er så isoleret i scope, at den bør køre i sin egen microverden. Men et system som håndterer månedlig betaling i Netflix bør ikke bygges op af en stak af services.

Det er meget simpelt: Der er en afgrundsdyb forskel mellem et kærnesystem og diverse garniturer i brugergrænsefladen. Et kærnesystem handler om kontoføring af penge, og indgår derfor i de allerfleste IT-systemer. Det kan også være andre aspekter end penge, hvor absolut konsistens kræves. Et kærnesystem er bygget op omkring én og kun en sammenhængende SQL-database, dvs et system af SQL-tabeller. Ovenpå kærnesystemet kan man bygge så mange mikroservices man lyster, de skader ikke, og kan sikkert bidrage til en bedre brugeroplevelse og glade brugere.

Disse 'fysikkens love' har nutidens IT-arkitekter ofte forbavsende store vanskeligheder ved at forstå. Men: man lærer det før eller siden.

  • 2
  • 2
Christian Nobel

Du skal være disciplineret og tænke meget over, hvorledes API’et fremstilles – der er ikke nogen anden måde at gøre det på.

.. et eksempel på hvordan man virkelig kan få lavet et uoverskueligt API, så skal man bare se på e-conomics kummerlige REST API.

  • 0
  • 0
Sune Marcher

Rådet i referatet om for enhver pris at undgå SQL-databaser, fordi det binder services sammen - er grotesk.


Nej, det er ikke dét der står.

Idéen er at flere services ikke skal have snablen i samme database, at snitfladen er et API og ikke SQL kode - og det er et riiiiiiiiiigtigt godt råd.

Hvis du har brug for noget så trivielt som atomic konto-overførsel laver du det naturligvis som én service med én database, det ville være fjollet at slice noget så trivielt op i flere services.

  • 4
  • 1
Peter Stricker

Referatet ovenfor cirkler rundt og rundt omkring det uløselige problem ved microservices: At services ikke kører i et fælles commit-space, og at der derfor ikke er styr på fx det klassiske bankproblem: Service A trækker 10 kr ud fra konto X, Service B skulle så have sat pengene ind på konto Y, men fejler. Resultatet: Banken vinder 10 kr. Det er 'bare et af livets fakta' ved distribuerede systemer, som det hedder i referatet ovenfor.

Rådet i referatet om for enhver pris at undgå SQL-databaser, fordi det binder services sammen - er grotesk.
I stedet bør man åbenbart køre et kæmpe cirkus af logs for at checke at fejl er sket... Hvad med at erstatte alle disse logs med en veldesignet SQL-database som registrerer systemets hændelser (set i relation til systemets formål). Dels er det meget nemmere at håndtere, dels gør det at fejl kan forebygges (...fælles commit) i stedet for at kompenseres (eller undskyldes) i efterfølgende sagsbehandling.


LIge præcis banksystemer minder på visse punkter om microservices. Hvis jeg vil overføre 100 kr. fra min konto i Microservicebanken til din konto i Sparekassen Mainframe, så foregår hævningen på min konto nødvendigvis i et andet commit-space end indsættelsen på din konto. Pengene bliver trukket på min konto i det øjeblik jeg gennemfører overførslen, men bliver først indsat på din konto næste bankdag.

Transaktionen overholder ikke engang ACID, idet den absolut ikke er atomic. Den må også nøjes med eventual consistency.

Jeg kan da godt forstå at du er fortørnet over at Tomer Gabel tillader sig at kalde det et af livets fakta. Men bankverdenen har altså været enige med ham i mange år.

  • 2
  • 0
Sune Marcher

Pengene bliver trukket på min konto i det øjeblik jeg gennemfører overførslen, men bliver først indsat på din konto næste bankdag.


Ganske fint indlæg, Peter. Jeg må hellere lige tilføje at jeg naturligvis kun mener at konto-overførsel er trivielt og kan gøres atomic når begge konti er i samme bank - ellers er det bestemt ikke trivielt, og når du involverer et clearing house har du et eventually consistent system :-)

Databasetransaktioner er lækre og konsistente og nemme at forstå når du har meget afgrænsede systemer, men de skalerer bare ikke fornuftigt. Vi kan ikke bygge en mainframe der er stor nok til at være hele verdens datasilo.

Og SQL er et udmærket sprog til databehandling, men det er en utroligt dårlig idé at lade snabel-i-database være et integrationspunkt.

  • 1
  • 0
Morten Bøgh

Jeg forsøgte i mit indlæg at komme et spadestik dybere end hr chefudvikleren, Tomer Gabel: De problemer han ser ved microservices hænger sammen med et ganske bestemt forhold i den fysiske virkelighed: Commit-spaces.
Hvis vi skal endnu dybere - og det skal vi åbenbart - så rummer den fysiske virkelighed to måder at koble selvstændige commit-spaces sammen: nemlig asynkron og synkron sammenkobling. Her gælder kort fortalt at asynkron er absolut sikker, commit-mæssig, men er langsom, og umuliggør at brugeren ved skærmen får en bindende besked om hvad der er sket. Den synrone er ikke sikker, men er hurtig. 'Hurtig' har mindre med fysisk hastighed at gøre, men mere med det forhold, at den synkrone kommunikation muliggør en stribe logisk sammenhængende handlinger i den 'oprindelige' microservervice indenfor samme commit-space. Mens asynkron forudsætter at den 'oprindelige' microservice udfører commit inden underliggende microservices commit'er.

Ja, banker kobler i vore dage deres kontohåndtering i forskellige banker absolut sikkert sammen via asynkron sammenkobling. Nej, verden kan ikke køre på én stor mainframe, det er også rigtigt.

Et eksempel: Det viser sig at bankkonto 'Y' i vores microbank-2 blev lukket for 3 microsekunder siden. Kontooverførslen kan ikke gennemføres. Vi kører med asynkron kommunikation. Dvs microbank-1 committer at der er hævet 10 kr fra konto 'X', men erfarer så efterføgelgende at pengene er endt på en fejl-opsamlingskonto i microbank-2. Transaktionen er reelt ikke gennemført. Dette kan så efterfølgende sorteres ud, men dialogmæssigt er det noget rod. Hvis vi i stedet brugte synkron kommunikation ville dialogen kunne svare korrekt i situationen: Du prøver at overføre til en konto som er lukket, prøv noget andet. Men sikkerheden mangler: Hvis microbank-2 svarer 'ok', er dette ikke troværdigt: microbank-2 kan være gået i dørken efter svaret er givet, og inden pengene faktisk er sat ind på konto-X. Derfor bruger bankerne altid asynkron sammenkobling.

Mit uvenlige håndtering af 'nutidens IT-arkitekter' skyldes dog ikke, at de alle har misforstået ovenstående. Det har de sikkert ikke. Problemet er deres manglende evne til at skelne mellem kærnesystemer og garniture i brugergrænsefladen. Et 'stort' kærnesystem opbygget omkring en SQL-base med en fælles commit-manager, er eneste løsning på ovenstående dilemma. Kærnesystemer bør være en del af arkitektens værktøjskasse, men er det typisk ikke. Det synes jeg godt Tomer Gabel kunne tænke lidt over.

  • 1
  • 1
Bjarne Nielsen

Mit uvenlige håndtering af 'nutidens IT-arkitekter' skyldes dog ikke, at de alle har misforstået ovenstående.

Engang arbejde jeg et sted, hvor vi ikke bare havde mange arkitekter, men også mange forskellige slags arkitekter. Nogle af dem valgte at placere server og database med 300 km afstand, og formåede derefter at blive forbløffede over, at turn-around tiden steg med godt 2 ms. Det måtte være en opsætningsfejl.

  • 1
  • 0
Log ind eller Opret konto for at kommentere