Dela via


Arkitekturformat för mikrotjänster

Mikrotjänster har blivit en populär arkitekturstil för att skapa molnprogram som är elastiska, mycket skalbara, kan distribueras oberoende av varandra och som kan utvecklas snabbt. Att skapa en framgångsrik mikrotjänstarkitektur kräver en grundläggande förändring i tankesättet. Det går utöver att dela upp ett program i mindre tjänster. Du måste också tänka om hur system utformas, distribueras och drivs.

En arkitektur för mikrotjänster består av en samling små, autonoma tjänster. Varje tjänst är fristående och bör implementera en enda affärsfunktion i en begränsad kontext. En avgränsad kontext är en naturlig division inom ett företag och ger en explicit gräns inom vilken en domänmodell finns.

Logiskt diagram över arkitekturformatet för mikrotjänster.

Vad är mikrotjänster?

Mikrotjänster är små, oberoende och löst kopplade komponenter som ett enda litet team med utvecklare kan skriva och underhålla. Varje tjänst hanteras som en separat kodbas, vilket gör att ett litet team kan hantera den effektivt. Eftersom tjänster kan distribueras oberoende av varandra kan team uppdatera befintliga tjänster utan att återskapa eller distribuera om hela programmet. Till skillnad från traditionella modeller som har ett centraliserat datalager ansvarar mikrotjänster för att bevara sina egna data eller externa tillstånd. De kommunicerar via väldefinierade API:er, vilket håller interna implementeringar dolda från andra tjänster. Den här arkitekturen stöder också flerspråkig programmering, vilket innebär att tjänsterna inte behöver dela samma teknikstack, bibliotek eller ramverk.

Komponenter

Förutom själva tjänsterna visas andra komponenter i en typisk mikrotjänstarkitektur:

  • Hantering eller orkestrering: Den här hanteringskomponenten hanterar orkestrering av mikrotjänster. Den schemalägger och distribuerar tjänster mellan noder, identifierar fel, återställer från fel och aktiverar automatisk skalning baserat på efterfrågan. En containerorkestreringsplattform som Kubernetes tillhandahåller vanligtvis den här funktionen. I molnbaserade miljöer tillhandahåller lösningar som Azure Container Apps hanterad orkestrering och inbyggd skalning. Dessa verktyg minskar distributionskomplexiteten och driftskostnaderna.

  • API-gateway: API-gatewayen fungerar som startpunkt för klienter. Klienter skickar begäranden till API-gatewayen i stället för att anropa tjänster direkt. Gatewayen vidarebefordrar dessa begäranden till lämpliga serverdelstjänster. Den hanterar även övergripande problem som autentisering, loggning och belastningsutjämning. I molnbaserade mikrotjänstarkitekturer stöder förenklade tjänstproxyservrar som Envoy och Nginx intern kommunikation från tjänst till tjänst. Den här typen av intern trafik, som kallas öst-västlig trafik, möjliggör avancerad routning och trafikkontroll.

  • Meddelandeorienterat mellanprogram: Meddelandeplattformar som Apache Kafka och Azure Service Bus möjliggör asynkron kommunikation i mikrotjänster genom att främja lös koppling och stöd för hög skalbarhet. De utgör grunden för händelsedrivna arkitekturer. Med den här metoden kan tjänster reagera på händelser i realtid och kommunicera via asynkrona meddelanden.

  • Observerbarhet: En effektiv strategi för observerbarhet hjälper teamen att upprätthålla systemets tillförlitlighet och lösa problem snabbt. Centraliserad loggning sammanför loggar för enklare diagnostik. Realtidsövervakning med programprestandaövervakningsagenter och ramverk som OpenTelemetry ger insyn i systemets hälsa och prestanda. Distribuerad spårning spårar begäranden över tjänstgränser. Det hjälper teamen att hitta flaskhalsar och förbättra prestandan.

  • Datahantering: En väl utformad databasarkitektur stöder autonomi och skalbarhet. Mikrotjänster använder ofta flerspråkig beständighet genom att välja olika databastyper, till exempel SQL eller NoSQL, baserat på varje tjänsts specifika behov. Den här metoden överensstämmer med domändriven design (DDD) och idén om begränsad kontext. Varje tjänst äger sina data och scheman. Det här ägarskapet minskar beroenden mellan tjänster och gör att tjänsterna kan utvecklas oberoende av varandra. Den här decentraliserade modellen förbättrar flexibilitet, prestanda och systemresiliens.

Fördelar

  • Smidighet: Eftersom mikrotjänster distribueras oberoende av varandra är det enklare att hantera felkorrigeringar och funktionsutgåvor. Du kan uppdatera en tjänst utan att distribuera om hela programmet och återställa en uppdatering om något går fel. Om du hittar ett fel i en del av programmet i många traditionella program kan det blockera hela lanseringsprocessen. En bugg kan till exempel stoppa nya funktioner om du behöver integrera, testa och publicera en felkorrigering.

  • Små, fokuserade team: En mikrotjänst bör vara tillräckligt liten för att ett enda funktionsteam ska kunna skapa, testa och distribuera den. Små teamstorlekar främjar mer flexibilitet. Stora team tenderar att vara mindre produktiva eftersom kommunikationen är långsammare, hanteringskostnaderna ökar och flexibiliteten minskar.

  • Liten kodbas: I ett monolitiskt program blir kodberoenden ofta sammanflätade med tiden. Att lägga till en ny funktion kan kräva ändringar i många delar av kodbasen. En mikrotjänstarkitektur undviker det här problemet genom att inte dela kod- eller datalager. Den här metoden minimerar beroenden och gör det enklare att introducera nya funktioner.

  • Blandning av tekniker: Teams kan välja den teknik som bäst passar deras tjänst genom att använda en blandning av teknikstackar efter behov.

  • Felisolering: Om en enskild mikrotjänst blir otillgänglig stör den inte hela programmet så länge som några överordnade mikrotjänster är utformade för att hantera fel korrekt. Du kan till exempel implementera kretsbrytarmönstret, eller så kan du utforma din lösning så att mikrotjänsterna kommunicerar med varandra med hjälp av asynkrona meddelandemönster.

  • Skalbarhet: Tjänster kan skalas separat. Med den här metoden kan du skala ut undersystem som kräver mer resurser utan att skala ut hela programmet. Använd en orkestrerare som Kubernetes för att lägga till en högre densitet av tjänster på en enda värd, vilket möjliggör effektivare resursanvändning.

  • Dataisolering: Det är enklare att uppdatera ett schema i en mikrotjänstarkitektur eftersom endast en mikrotjänst påverkas. Monolitiska program kan däremot komplicera schemaändringar, eftersom flera komponenter ofta interagerar med samma data. Den här delade åtkomsten gör alla ändringar potentiellt riskfyllda.

Utmaningar

Fördelarna med mikrotjänster kommer med kompromisser. Tänk på följande utmaningar innan du skapar en arkitektur för mikrotjänster:

  • Komplexitet: Ett mikrotjänstprogram har fler rörliga delar än motsvarande monolitiska program. Varje tjänst är enklare, men hela systemet som helhet är mer komplext. Se till att du överväger utmaningar som tjänstidentifiering, datakonsekvens, transaktionshantering och kommunikation mellan tjänster när du utformar ditt program.

  • Utveckling och testning: Att skriva en liten tjänst som förlitar sig på andra beroende tjänster kräver en annan metod än att skriva ett traditionellt monolitiskt eller skiktat program. Befintliga verktyg är inte alltid utformade för att fungera med tjänstberoenden. Det kan vara svårt att omstrukturera över tjänstgränser. Det är också svårt att testa tjänstberoenden, särskilt när programmet utvecklas snabbt.

  • Brist på styrning: Den decentraliserade metoden för att skapa mikrotjänster har fördelar, men det kan också leda till problem. Du kan få så många olika språk och ramverk att programmet blir svårt att underhålla. Det kan vara bra att införa vissa projektomfattande standarder, utan att alltför begränsa teamens flexibilitet. Den här metoden gäller särskilt för övergripande funktioner, till exempel loggning.

  • Nätverksbelastning och svarstid: Användningen av många små, detaljerade tjänster kan leda till mer kommunikation mellan tjänster. Om kedjan med tjänstberoenden blir för lång (tjänst A anropar B, som anropar C...) kan den extra svarstiden också bli ett problem. Du måste utforma API:er noggrant. Undvik alltför pratsamma API:er, tänk på serialiseringsformat och leta efter platser där du kan använda asynkrona kommunikationsmönster som mönstretQueue-Based belastningsutjämning.

  • Dataintegritet: Varje mikrotjänst ansvarar för sin egen datapersistence. Därför kan datakonsekvens mellan flera tjänster vara en utmaning. Olika tjänster bevarar data vid olika tidpunkter, med hjälp av olika teknik och med potentiellt olika framgångsnivåer. När mer än en mikrotjänst är involverad i att bevara nya eller ändrade data är det osannolikt att den fullständiga dataändringen kan betraktas som en atomisk, konsekvent, isolerad och varaktig transaktion (ACID). I stället är tekniken mer i linje med Basically Available, Soft State, Eventual Consistency (BASE). Använd eventuell konsistens där det är möjligt.

  • Ledning: En lyckad mikrotjänstarkitektur kräver en mogen DevOps-kultur. Korrelerad loggning mellan tjänster kan vara utmanande. Loggning måste vanligtvis korrelera flera tjänstanrop för en enskild användaråtgärd.

  • Versionshantering: Uppdateringar av en tjänst får inte bryta tjänster som är beroende av den. Flera tjänster kan uppdateras när som helst, så utan noggrann design kan du få problem med bakåt- eller framåtkompatibilitet.

  • Kompetensuppsättning: Mikrotjänster är mycket distribuerade system. Utvärdera noggrant om teamet har de kunskaper och den erfarenhet som behövs för att lyckas.

Metodtips

  • Modellera tjänster runt affärsdomänen. Använd DDD för att identifiera avgränsade kontexter och definiera tydliga tjänstgränser. Undvik att skapa alltför detaljerade tjänster, vilket kan öka komplexiteten och minska prestanda.

  • Decentralisera allt. Enskilda team ansvarar för att utforma och bygga tjänster från slutpunkt till slutpunkt. Undvik att dela kod eller datascheman.

  • Standardisera dina teknikval genom att begränsa antalet språk och ramverk som du använder. Upprätta plattformsomfattande standarder för loggning, övervakning och distribution.

  • Datalagring ska vara privat för den tjänst som äger data. Använd den bästa lagringen för varje tjänst och datatyp.

  • Tjänster kommunicerar via väl utformade API:er. Undvik att läcka implementeringsinformation. API:er bör modellera domänen, inte den interna implementeringen av tjänsten.

  • Undvik koppling mellan tjänster. Orsaker till koppling är delade databasscheman och fasta kommunikationsprotokoll.

  • Förbättra säkerheten med hjälp av ömsesidig transportnivåsäkerhet (mTLS) för tjänst-till-tjänst-kryptering. Implementera rollbaserad åtkomstkontroll och använd API-gatewayer för att tillämpa principer.

  • Avlasta övergripande problem, till exempel autentisering och Secure Sockets Layer-avslutning, till gatewayen. Tjänstnät och ramverk som Dapr kan också hjälpa till med vanliga övergripande problem som mTLS-autentisering och återhämtning.

  • Håll domänkunskapen borta från gatewayen. Gatewayen ska hantera och dirigera klientbegäranden utan någon kunskap om affärsregler eller domänlogik. Annars blir gatewayen ett beroende och kan orsaka koppling mellan tjänster.

  • Tjänsterna bör ha lös koppling och hög funktionell sammanhållning. Funktioner som sannolikt kommer att ändras tillsammans bör paketeras och distribueras tillsammans. Om de finns i separata tjänster blir tjänsterna nära kopplade, eftersom en ändring i en tjänst kräver att den andra tjänsten uppdateras. Alltför pratsam kommunikation mellan två tjänster kan vara ett symptom på nära koppling och låg sammanhållning.

  • Använd CI/CD-pipelines (kontinuerlig integrering och kontinuerlig distribution) för att automatisera testning och distribution. Distribuera tjänster oberoende av varandra och övervaka distributionshälsa.

  • Isolera fel. Använd återhämtningsstrategier för att förhindra fel i en tjänst från att sammanhängande. Mer information finns i Återhämtningsmönster och Utforma tillförlitliga program.

  • Använd kaosteknik för att testa motståndskraften i din mikrotjänstarkitektur och dess beroenden. Utvärdera och förbättra hur systemet hanterar partiella fel.

  • Implementera centraliserad loggning, distribuerad spårning (OpenTelemetry) och insamling av mått för att säkerställa observerbarhet.

Antimönster för mikrotjänster

När du utformar och implementerar mikrotjänster uppstår ofta specifika fallgropar som kan undergräva fördelarna med den här arkitekturstilen. Genom att känna igen dessa antimönster kan teamen undvika kostsamma misstag och bygga mer motståndskraftiga och underhållsbara system. Undvik följande antimönster:

  • Att implementera mikrotjänster utan djup förståelse för affärsdomänen resulterar i dåligt anpassade tjänstgränser och undergräver de avsedda fördelarna.

  • Att utforma händelser som är beroende av tidigare eller framtida händelser strider mot principen om atomiska och fristående meddelanden. Det här beroendet tvingar konsumenterna att vänta och minska systemets tillförlitlighet.

  • Att använda databasentiteter som händelser exponerar intern tjänstinformation och misslyckas ofta med att förmedla rätt affärsidé, vilket leder till nära kopplade och otydliga integreringar.

  • Att undvika dataduplicering till varje pris är ett antimönster. Användning av mönster som materialiserade vyer för att underhålla lokala kopior förbättrar tjänstens autonomi och minskar beroenden mellan tjänster.

  • Användning av allmänna händelser tvingar konsumenter att tolka och filtrera meddelanden. Den här metoden ger onödig komplexitet och minskar tydligheten i händelsedriven kommunikation.

  • Att dela gemensamma bibliotek eller beroenden mellan mikrotjänster skapar en nära koppling, vilket gör förändringar riskabla och utbredda och strider mot principen om självständiga tjänster.

  • Att exponera mikrotjänster direkt för konsumenter resulterar i nära koppling, skalbarhetsproblem och säkerhetsrisker. Med hjälp av en API-gateway får du en ren, hanterbar och säker startpunkt.

  • Konfigurationsvärden som hålls inom mikrotjänster tätt kopplar dem till specifika miljöer, vilket gör utplaceringarna svårare. Men externalisering av konfigurationen främjar flexibilitet och miljöportabilitet.

  • Inbäddning av säkerhetslogik som tokenvalidering direkt i mikrotjänster komplicerar deras kod och underhåll. Alternativt kan avlastning av säkerhet till dedikerade komponenter hålla tjänsterna fokuserade och renare.

  • Om du inte kan abstrahera vanliga mikrotjänstuppgifter resulterar det i repetitiv, felbenägen kod och begränsar flexibiliteten. Du kan också använda abstraktionsramverk som Dapr förenklar utvecklingen genom att ta bort affärslogik från infrastrukturproblem.

Skapa en arkitektur för mikrotjänster

Följande artiklar innehåller en strukturerad metod för att utforma, skapa och använda en mikrotjänstarkitektur.

Använd domänanalys: Om du vill undvika vanliga fallgropar när du utformar mikrotjänster använder du domänanalys för att definiera dina mikrotjänstgränser. Använd följande steg:

  1. Använda domänanalys för att utforma mikrotjänstmodeller.
  2. Använda taktisk DDD för att utforma mikrotjänster.
  3. Identifiera gränser för mikrotjänster.

Utforma tjänsterna: Mikrotjänster kräver en decentraliserad och flexibel metod för att utforma och skapa program. Mer information finns i Designa en arkitektur för mikrotjänster.

Arbeta i produktion: Eftersom mikrotjänstarkitekturer distribueras måste du ha robusta åtgärder för distribution och övervakning.