Identifiera gränser för mikrotjänster

Azure DevOps

Vilken är rätt storlek för en mikrotjänst? Du hör ofta något om effekten av, "inte för stor och inte för liten" - och även om det verkligen är korrekt, är det inte till stor hjälp i praktiken. Men om du börjar med en noggrant utformad domänmodell är det mycket enklare att resonera om mikrotjänster.

Diagram över avgränsade kontexter.

I den här artikeln används en tjänst för drönarleverans som ett exempel som körs. Du kan läsa mer om scenariot och motsvarande referensimplementering här.

Från domänmodell till mikrotjänster

I föregående artikel definierade vi en uppsättning begränsade kontexter för ett drone delivery-program. Sedan tittade vi närmare på en av dessa begränsade kontexter, den begränsade kontexten för leverans, och identifierade en uppsättning entiteter, aggregeringar och domäntjänster för den begränsade kontexten.

Nu är vi redo att gå från domänmodell till programdesign. Här är en metod som du kan använda för att få ut mikrotjänster från domänmodellen.

  1. Börja med en avgränsad kontext. Generellt bör funktionerna i en mikrotjänst inte omfatta fler än en avgränsad kontext. Per definition markerar en avgränsad kontext gränsen för en viss domänmodell. Om du ser att en mikrotjänst blandar olika domänmodeller är det ett tecken på att du kan behöva gå tillbaka och precisera domänanalysen.

  2. Titta sedan på aggregaten i domänmodellen. Aggregat är ofta bra kandidater till att vara mikrotjänster. Ett väldesignat aggregat har många egenskaper gemensamt med en väldesignad mikrotjänst, till exempel följande:

    • Aggregat kommer från affärskrav i stället för tekniska frågor såsom dataåtkomst eller meddelanden.
    • Aggregat bör ha hög funktionell sammanhållning.
    • Aggregat är gränser för beständighet.
    • Aggregat bör vara löst kopplade.
  3. Domäntjänster är också bra kandidater för mikrotjänster. Domäntjänster är tillståndslösa åtgärder som omfattar flera aggregat. Ett vanligt exempel är ett arbetsflöde som inbegriper flera mikrotjänster. Vi kommer att titta på ett exempel på detta i programmet för drönarleverans.

  4. Slutligen bör du beakta icke-funktionella krav. Titta på faktorer som teamstorlek, datatyper, tekniker samt krav på skalbarhet, tillgänglighet och säkerhet. De här faktorerna kan göra att du delar upp mikrotjänsten ytterligare till två eller fler mindre tjänster, eller att du gör det motsatta och kombinerar flera mikrotjänst till en och samma.

När du har identifierat mikrotjänsterna i ditt program verifierar du din design mot följande kriterier:

  • Varje tjänst har ett enda ansvar.
  • Det finns inga pratsamma samtal mellan tjänster. Om uppdelningen av funktioner i två tjänster gör att de blir alltför pratsamma kan det vara ett symptom på att dessa funktioner hör hemma i samma tjänst.
  • Varje tjänst är tillräckligt liten för att kunna byggas av ett litet team som arbetar oberoende av varandra.
  • Det finns inga beroenden som kräver att två eller flera tjänster distribueras i låssteg. Det bör alltid vara möjligt att distribuera en tjänst utan att omdistribuera andra tjänster.
  • Tjänsterna är inte nära kopplade och kan utvecklas oberoende av varandra.
  • Dina tjänstgränser skapar inte problem med datakonsekvens eller integritet. Ibland är det viktigt att upprätthålla datakonsekvens genom att placera funktioner i en enda mikrotjänst. Som sagt, överväg om du verkligen behöver stark konsekvens. Det finns strategier för att hantera slutlig konsekvens i ett distribuerat system, och fördelarna med att dela upp tjänster överväger ofta utmaningarna med att hantera slutlig konsekvens.

Framför allt är det viktigt att vara pragmatisk och komma ihåg att domändriven design är en iterativ process. Om du är osäker ska du börja med mer generella mikrotjänster. Det är enklare att dela upp en mikrotjänst i två mindre tjänster än att refaktorisera funktioner mellan flera befintliga mikrotjänster.

Exempel: Definiera mikrotjänster för drone delivery-programmet

Kom ihåg att utvecklingsteamet hade identifierat de fyra aggregeringarna – Leverans, Paket, Drönare och Konto – och två domäntjänster, Scheduler och Supervisor.

Leverans och paket är självklara kandidater för mikrotjänster. Scheduler och Supervisor samordnar de aktiviteter som utförs av andra mikrotjänster, så det är klokt att implementera dessa domäntjänster som mikrotjänster.

Drönare och konto är intressanta eftersom de tillhör andra avgränsade kontexter. Ett alternativ är att Scheduler anropar kontexterna Drone och Account direkt. Ett annat alternativ är att skapa mikrotjänster för drönare och konton i kontexten Leveransavgränsad. Dessa mikrotjänster skulle medla mellan de avgränsade kontexterna genom att exponera API:er eller datascheman som är mer lämpade för leveranskontexten.

Informationen om de drönar- och kontoavgränsade kontexterna ligger utanför den här vägledningen, så vi skapade falska tjänster för dem i vår referensimplementering. Men här är några faktorer att tänka på i den här situationen:

  • Vad är nätverkskostnaderna för att anropa direkt i den andra begränsade kontexten?

  • Är dataschemat för den andra begränsade kontexten lämpligt för den här kontexten, eller är det bättre att ha ett schema som är anpassat efter den här begränsade kontexten?

  • Är den andra begränsade kontexten ett äldre system? I så fall kan du skapa en tjänst som fungerar som ett lager mot korruption för att översätta mellan det äldre systemet och det moderna programmet.

  • Vad är teamstrukturen? Är det enkelt att kommunicera med teamet som ansvarar för den andra avgränsade kontexten? Om inte kan du minska kostnaderna för kommunikation mellan team genom att skapa en tjänst som medlar mellan de två kontexterna.

Hittills har vi inte övervägt några icke-funktionella krav. När utvecklingsteamet tänkte på programmets dataflödeskrav bestämde de sig för att skapa en separat inmatningsmikrotjänst som ansvarar för att mata in klientbegäranden. Den här mikrotjänsten implementerar belastningsutjämning genom att placera inkommande begäranden i en buffert för bearbetning. Scheduler läser begäranden från bufferten och kör arbetsflödet.

Icke-funktionella krav ledde till att teamet skapade ytterligare en tjänst. Alla tjänster har hittills gått ut på att schemalägga och leverera paket i realtid. Men systemet måste också lagra historiken för varje leverans i långsiktig lagring för dataanalys. Teamet övervägde att göra detta till leveranstjänstens ansvar. Kraven för datalagring är dock helt olika för historisk analys jämfört med åtgärder under flygning (se Dataöverväganden). Därför bestämde sig teamet för att skapa en separat leveranshistoriktjänst som lyssnar efter DeliveryTracking-händelser från leveranstjänsten och skriver händelserna till långsiktig lagring.

Följande diagram visar designen just nu:

Diagram som visar utformningen av mikrotjänster för drone delivery-programmet.

Ladda ned en Visio-fil med den här arkitekturen.

Nästa steg

Nu bör du ha en tydlig förståelse för syftet med och funktionerna för varje mikrotjänst i din design. Nu kan du skapa systemet.