Mönster: Microservice Architecture (Svenska)
Kontext
Du utvecklar en serverapplikation på serversidan. Den måste stödja en mängd olika klienter inklusive stationära webbläsare, mobila webbläsare och inbyggda mobilapplikationer. Applikationen kan också exponera ett API för tredje part att konsumera. Det kan också integreras med andra applikationer via antingen webbtjänster eller en meddelandemäklare. Applikationen hanterar förfrågningar (HTTP-förfrågningar och meddelanden) genom att utföra affärslogik; åtkomst till en databas; utbyte av meddelanden med andra system; och returnerar ett HTML / JSON / XML-svar. Det finns logiska komponenter som motsvarar olika funktionella områden i applikationen.
Problem
Vad är programmets distributionsarkitektur?
Krafter
- Det finns ett team av utvecklare som arbetar med applikationen
- Nya teammedlemmar måste snabbt bli produktiva
- Applikationen måste vara lätt att förstå och ändra
- Du vill öva kontinuerlig distribution av applikationen
- Du måste köra flera instanser av applikationen på flera datorer för att uppfylla skalbarhet och tillgänglighetskrav
- Du vill dra nytta av nya tekniker (ramar, programmeringsspråk, etc)
Lösning
Definiera en arkitektur som strukturerar applikationen som en uppsättning löst kopplade, samarbetande tjänster. Detta tillvägagångssätt motsvarar Y-axeln för Scale Cube. Varje tjänst är:
- Mycket underhållbar och testbar – möjliggör ra pid och frekvent utveckling och distribution
- Löst i kombination med andra tjänster – gör det möjligt för ett team att arbeta självständigt merparten av tiden på sina tjänster utan att påverkas av förändringar i andra tjänster och utan att påverka andra tjänster
- Kan distribueras oberoende – gör det möjligt för ett team att distribuera sin tjänst utan att behöva samordna med andra team
- Kan utvecklas av ett litet team – viktigt för hög produktivitet genom att undvika hög kommunikationschef för stora team
Tjänster kommunicerar med antingen synkrona protokoll som HTTP / REST eller asynkrona protokoll som AMQP. Tjänster kan utvecklas och distribueras oberoende av varandra. Varje tjänst har sin egen databas för att kopplas bort från andra tjänster. Datakonsistensen mellan tjänster upprätthålls med Saga-mönstret
Om du vill lära dig mer om en tjänsts natur, läs den här artikeln.
Exempel
Fiktiva e-handelstillämpningar den
Låt oss föreställa oss att du bygger en e-handelsapplikation som tar emot beställningar från kunder, verifierar lager och tillgänglig kredit och skickar dem. Applikationen består av flera komponenter inklusive StoreFrontUI, som implementerar användargränssnittet , tillsammans med några backend-tjänster för kontroll av kredit, underhåll av lager- och leveransorder. Applikationen består av en uppsättning tjänster.
Visa mig koden
Se exempelapplikationerna som utvecklats av Chris Richardson. Dessa exempel på Github illustrerar olika aspekter av mikrotjänstarkitekturen.
Resulterande sammanhang
Fördelar
Denna lösning har ett antal fördelar:
- Möjliggör kontinuerlig leverans och distribution av stora, komplexa applikationer.
- Förbättrad underhållsförmåga – varje tjänst är relativt liten och det är lättare att förstå och ändra
- Bättre testbarhet – tjänster är mindre och snabbare att testa
- Bättre distribution – tjänster kan distribueras oberoende
- Det gör att du kan organisera utvecklingsarbetet kring flera, autonoma team. Varje (så kallat två pizza) team äger och ansvarar för en eller flera tjänster. Varje team kan utveckla, testa, distribuera och skala sina tjänster oberoende av alla andra team.
- Varje mikrotjänst är relativt liten:
- Enklare för en utvecklare att förstå
- IDE är snabbare vilket gör utvecklare mer produktiva
- Applikationen startar snabbare, vilket gör utvecklare mer produktiva och påskyndar implementeringar
- Förbättrad felisolering. Till exempel, om det finns en minnesläcka i en tjänst kommer endast den tjänsten att påverkas. De andra tjänsterna kommer att fortsätta att hantera förfrågningar. I jämförelse kan en felaktig komponent i en monolitisk arkitektur få ner hela systemet.
- Eliminerar alla långsiktiga åtaganden för en teknikstack. När du utvecklar en ny tjänst kan du välja en ny teknikstack. På samma sätt kan du skriva om den med en ny teknikstack när du gör stora förändringar i en befintlig tjänst.
Nackdelar
Denna lösning har ett antal nackdelar:
- Utvecklare måste ta itu med den extra komplexiteten att skapa ett distribuerat system:
- Utvecklare måste implementera kommunikationsmekanismen mellan tjänster och hantera partiellt misslyckande
- Att implementera förfrågningar som sträcker sig över flera tjänster är svårare
- Att testa interaktionen mellan tjänster är mer svårt
- Att implementera förfrågningar som sträcker sig över flera tjänster kräver noggrann samordning mellan lagen
- Utvecklarverktyg / IDE: er är inriktade på att bygga monolitiska applikationer och ger inte uttryckligt stöd för att utveckla distribuerade applikationer.
- Installationskomplexitet. I produktionen finns det också den operativa komplexiteten att distribuera och hantera ett system som består av många olika tjänster.
- Ökad minnesförbrukning. Mikrotjänstarkitekturen ersätter N monolitiska applikationsinstanser med NxM-tjänsterinstanser. Om varje tjänst körs i sin egen JVM (eller motsvarande), vilket vanligtvis är nödvändigt för att isolera förekomsterna, finns det M-gånger så många JVM-körningar. Dessutom, om varje tjänst körs på sin egen virtuella dator (t.ex. EC2-instans), som är fallet på Netflix, är omkostnaderna ännu högre.
Problem
Det finns dessutom många problem som du måste ta itu med.
När ska du använda mikrotjänstarkitekturen?
En utmaning med att använda detta tillvägagångssätt är att bestämma när det är vettigt att använda den. När man utvecklar den första versionen av en applikation har du ofta inte de problem som detta tillvägagångssätt löser. Dessutom, med hjälp av en detaljerad, distribuerad arkitektur kommer att bromsa utvecklingen. Detta kan vara ett stort problem för nystartade företag vars största utmaning ofta är hur man snabbt utvecklar affärsmodellen och tillhörande Att använda splittringar på Y-axeln kan göra det mycket svårare att iterera snabbt. Senare, men när utmaningen är hur man skalar och du behöver använda funktionell sönderdelning, kan de trassliga beroenden göra det svårt att bryta ner din monolitiska applikation till en uppsättning tjänster.
Hur man sönderdelar applikationen tion till tjänster?
En annan utmaning är att bestämma hur man delar upp systemet i mikrotjänster. Detta är väldigt mycket en konst, men det finns ett antal strategier som kan hjälpa:
- Sönderdelas efter affärsförmåga och definiera tjänster som motsvarar affärsmöjligheter.
- Sönderdelas efter underdomän som drivs av domän.
- Sönderdelas med verb eller användningsfall och definiera tjänster som är ansvariga för vissa åtgärder . t.ex. a
Shipping Service
som ansvarar för leverans av fullständiga beställningar. - Sönderdelas med substantiv eller resurser genom att definiera en tjänst som ansvarar för alla operationer på enheter / resurser för en viss typ. t.ex. en
Account Service
som ansvarar för hanteringen av användarkonton.
Helst bör varje tjänst ha en liten uppsättning ansvarsområden. (farbror) Bob Martin talar om att utforma klasser med hjälp av Single Responsibility Principle (SRP). SRP definierar ett klassansvar som en anledning att ändra, och säger att en klass bara ska ha en anledning att ändra. Det är vettigt att tillämpa SRP på tjänstedesign också.
En annan analogi som hjälper till med design av tjänster är utformningen av Unix-verktyg. Unix erbjuder ett stort antal verktyg som grep, cat och find. Varje verktyg gör exakt en sak, ofta exceptionellt bra, och är tänkt att kombineras med andra verktyg som använder ett skalskript för att utföra komplexa uppgifter.
Hur bibehålls datakonsistens?
För att säkerställa lös koppling har varje tjänst sin egen Databas. Att upprätthålla datakonsistens mellan tjänster är en utmaning eftersom två fas / kommit / distribuerade transaktioner inte är det ett alternativ för många applikationer. En applikation måste istället använda Saga-mönstret. En tjänst publicerar en händelse när dess data ändras. Andra tjänster konsumerar den händelsen och uppdaterar deras data. Det finns flera sätt att uppdatera data på ett tillförlitligt sätt och publicera händelser inklusive händelsekällor och Transaktionslogging.
Hur implementerar jag frågor?
En annan utmaning är att implementera frågor som behöver hämta data som ägs av flera tjänster.
- API CQRS-mönster (Composition and Command Query Responsibility Segregation).
Det finns många mönster relaterade till mikrotjänstmönstret. Den monolitiska arkitekturen är ett alternativ till mikrotjänstarkitekturen. De andra mönstren adresserar problem som du kommer att stöta på när du använder mikrotjänstarkitekturen.
- Sönderdelningsmönster
- Sönderdelas efter affärsförmåga
- Sönderdelas efter underdomän
- Databasen per tjänstemönster beskriver hur varje tjänsten har en egen databas för att säkerställa lös koppling.
- API Gateway-mönstret definierar hur klienter får åtkomst till tjänsterna i en mikrotjänstarkitektur.
- Upptäcktsmönstret på klientsidan och på serversidan används för att dirigera förfrågningar om en klient tillgänglig tjänsteinstans i en mikrotjänstarkitektur.
- Mönster för meddelande- och fjärrproceduranrop är två olika sätt som tjänster kan kommunicera.
- Mönstret Enkel tjänst per värd och Flera tjänster per värd är två olika distributionsstrategier.
- Tvärgående mönster: Microservice chassimönster och extern konfiguration
- Testmönster: Service Component Test och Service Integration Contract Test
- Circuit Brytare
- Åtkomsttoken
- Observationsmönster:
- Loggaggregering
- Applikationsmätvärden
- Granskningsloggning
- Distribuerad spårning
- Undantagsspårning
- Hälsokontroll-API
- Loggdistribution och ändringar
- UI-mönster:
- Fragtsammansättning på serversidan
- UI-sammansättning på klientsidan
Kända användningsområden
De flesta storskaliga webbplatser inklusive Netflix, Amazon och eBay har utvecklats från en monolitisk arkitektur till en mikroservicearkitektur.
Netflix, som är en mycket populär videostreamingtjänst som ansvarar för upp till 30% av internettrafiken, har en storskalig, serviceorienterad arkitektur. De hanterar över en miljard samtal per dag till deras videostreaming-API från över 800 olika typer av enheter. Varje API kallar fans till i genomsnitt sex samtal till backend-tjänster.
Amazon.com hade ursprungligen en tvåskiktsarkitektur. För att skala dem migrerade de till en tjänstorienterad arkitektur bestående av hundratals backend-tjänster. Flera applikationer kallar dessa tjänster inklusive applikationerna som implementerar Amazon.com-webbplatsen och webbtjänstens API. Amazon.com-webbplatsapplikationen ringer 100-150 tjänster för att få data som brukade bygga en webbsida.
Auktionswebbplatsen ebay.com utvecklades också från en monolitisk arkitektur till en serviceorienterad arkitektur. Applikationsnivån består av flera oberoende applikationer. Varje applikation implementerar affärslogiken för ett specifikt funktionsområde som att köpa eller sälja. Varje applikation använder X-axeldelningar och vissa applikationer som sökning använder Z-axeldelningar. eBay.com tillämpar också en kombination av X-, Y- och Z-stilskalning på databasnivå.
Det finns många andra exempel på företag som använder mikrotjänstarkitekturen.
Chris Richardson har exempel på mikrotjänstbaserade applikationer.
Se även
Se min Key Freeze-nyckel 2018, som ger en bra introduktion till mikroservicearkitekturen.