Skottmönster

Bulkhead-mönstret är en typ av programdesign som är tolerant mot fel. I en skottarkitektur, även kallad cellbaserad arkitektur, isoleras element i ett program i pooler så att de andra elementen fortsätter att fungera om det ena misslyckas. Skottmönstret har fått sitt namn efter de sektionerade partitionerna (skott) på ett fartygs skrov. Om skrovet på ett fartyg blir skadat, fylls endast det skadade avsnittet med vatten, vilket förhindrar att fartyget sjunker.

Kontext och problem

Ett molnbaserat program kan innehålla flera tjänster och varje tjänst har en eller flera konsumenter. Överdriven belastning eller fel i en tjänst påverkar alla användare av tjänsten.

Dessutom kan en konsument skicka begäranden till flera tjänster samtidigt och använda resurser för varje begäran. När konsumenten skickar en begäran till en felkonfigurerad eller icke-svarar-tjänst kan de resurser som klientens begäran använder förbli otillgängliga under en längre period. När begäranden till tjänsten fortsätter kan dessa resurser vara uttömda. Till exempel kan klientens anslutningspool vara slut. Då påverkas konsumentens begäranden till andra tjänster. Slutligen kan konsumenten inte skicka begäranden till andra tjänster, inte bara den ursprungliga tjänsten som inte svarar.

Resursöverbelastning påverkar tjänster som har flera konsumenter. Många begäranden från en klient kan uttömma tillgängliga resurser i tjänsten. Resursöverbelastning kan innebära att andra konsumenter inte kan använda tjänsten, vilket orsakar en sammanhängande feleffekt.

Lösning

Partitionera tjänstinstanser i olika grupper baserat på krav på konsumentbelastning och tillgänglighet. Den här designen hjälper till att isolera fel. Du kan upprätthålla tjänstfunktioner för vissa konsumenter, även under ett fel.

En konsument kan också partitionera resurserna för att säkerställa att resurser som används för att anropa en tjänst inte påverkar de resurser som används för att anropa en annan tjänst. En konsument som anropar flera tjänster kan till exempel tilldelas en anslutningspool för varje tjänst. Om en tjänst börjar misslyckas påverkar den bara den anslutningspool som tilldelats för den tjänsten. Konsumenten kan fortsätta att använda andra tjänster.

Det här mönstret ger följande fördelar:

  • Isolerar användare och tjänster från kaskadfel. Ett problem som påverkar en konsument eller tjänst kan isoleras inom en egen avskärmning för att förhindra att hela lösningen fallerar.

  • Bevarar vissa funktioner om ett tjänstfel inträffar. Andra tjänster och funktioner i programmet fortsätter att fungera.

  • Ger olika kvalitet på tjänstnivåer för användning av program. Du kan konfigurera en högprioriterad konsumentpool så att den använder tjänster med hög prioritet.

Följande diagram visar barriärer som är utformade kring anslutningspooler som anropar enskilda tjänster. Om service A misslyckas eller orsakar ett problem isoleras anslutningspoolen, så endast arbetsbelastningar som använder trådpoolen som tilldelats service A påverkas. Arbetsbelastningar som använder tjänst B och C påverkas inte och kan fortsätta arbeta utan avbrott.

Diagram som visar avdelningar kring anslutningspooler som anropar enskilda tjänster.

Diagram som visar två arbetsbelastningar, arbetsbelastning 1 och arbetsbelastning 2, och tre tjänster, Service A, Service B och Service C. Arbetsbelastning 1 använder en anslutningspool som är tilldelad till Service A. Arbetsbelastning 2 använder två anslutningspooler. En anslutningspool tilldelas service B och den andra tilldelas till Service C. Anslutningspoolen som arbetsbelastning 1 använder är isolerad. De anslutningspooler som Workload 2 använder kan fortsätta att anropa Service B och Service C.

Följande diagram visar flera klienter som anropar en enda tjänst. Varje klient tilldelas till en separat tjänstinstans. Klient 1 gör för många begäranden och överbelastar instansen. Eftersom varje tjänstinstans är isolerad från de andra kan de andra klienterna fortsätta att göra anrop.

Diagram som visar flera klienter som anropar en enda tjänst.

Diagram som visar tre klienter, Klient 1, Klient 2 och Klient 3, och tre tjänstinstanser som var och en utgör en del av Service A. Varje klient ansluter till sin egen tjänstinstans. Tjänstinstanserna är isolerade. Om Klient 1 överbelastar instansen påverkas inte klienterna 2 och 3.

Problem och överväganden

Tänk på följande när du bestämmer hur du ska implementera det här mönstret:

  • Definiera partitioner runt affärsmässiga och tekniska krav för programmet.

  • Om du använder taktisk domändriven design för att utforma mikrotjänster bör partitionsgränserna överensstämma med de avgränsade kontexterna.

  • När du partitionerar tjänster eller användare i skott bör du ta hänsyn till isoleringsnivån som tekniken erbjuder och omkostnaderna i fråga om kostnad, prestanda och hanterbarhet.

  • Om du vill tillhandahålla mer avancerad felhantering kan du överväga att kombinera avskiljare med återförsök, kretsbrytare och strypningsmönster.

  • När du delar upp konsumenter i separata enheter bör du överväga att använda processer, trådpooler och semaforer. Projekt som resilience4j och Polly erbjuder en ram för att skapa skydd mot överbelastning av konsumenttjänster.

  • När du partitionerar tjänster i skott bör du överväga att distribuera dem till separata virtuella datorer, containrar eller processer. Containrar erbjuder en bra balans mellan resursisolering och relativt låg kostnad.

  • Tjänster som kommunicerar med hjälp av asynkrona meddelanden kan isoleras via olika uppsättningar köer. Varje kö kan ha en dedikerad uppsättning instanser som bearbetar meddelanden i kön eller en enda grupp med instanser som använder en algoritm för att ta ut från kön och starta bearbetningen.

  • Fastställ granularitetsnivån för de vattentäta skotten. Om du till exempel vill distribuera klientorganisationer mellan partitioner kan du placera varje klientorganisation i en separat partition eller placera flera klienter i en partition.

  • Övervaka varje partitions prestanda- och serviceavtal (SLA).

  • Använd inbyggda plattformskontroller, till exempel Hastighetsbegränsningar för Azure API Management, RU-isolering (Azure Cosmos DB Request Unit) och resursgränser i Azure Kubernetes Service (AKS) eller Azure Container Apps. Återskapa inte dessa mekanismer för begränsning och isolering i programkoden.

  • AI- och inferenslaster kräver ofta strikta gränser på grund av krav på distributionskvoter och samtidighetsgränser, till exempel att isolera Azure OpenAI-distributioner för varje arbetslast eller för varje hyresgäst.

När du ska använda det här mönstret

Använd det här mönstret i sådana här scenarier:

  • Du vill isolera resurser för specifika beroenden så att ett avbrott i en tjänst inte påverkar hela programmet.
  • Du vill isolera kritiska konsumenter från standardkonsumenter.
  • Du måste skydda programmet från sammanhängande fel.

Det här mönstret kanske inte är lämpligt när:

  • Mindre effektiv användning av resurser kanske inte är acceptabelt i projektet.
  • Den extra komplexiteten är inte nödvändig.

Design av arbetsbelastning

Utvärdera hur du använder bulkhead-mönstret i en arbetsbelastnings design för att hantera de mål och principer som beskrivs i Grundpelarna i Azure Well-Architected Framework. Följande tabell innehåller vägledning om hur det här mönstret stöder målen för varje pelare.

Grundpelare Så här stöder det här mönstret pelarmål
Tillförlitlighets designbeslut hjälper din arbetsbelastning att bli motståndskraftig mot funktionsfel och säkerställer att den återställer sig till ett fullständigt fungerande tillstånd när ett fel uppstår. Strategin för felisolering, som infördes genom avsiktlig och fullständig segmentering mellan komponenter, syftar till att begränsa felen till det skott som upplever problemet, vilket förhindrar att det påverkar andra skott.

- RE:02 Kritiska flöden
- RE:07 Självbevarande
Beslut om säkerhetsdesign bidrar till att säkerställa konfidentialitet, integritet och tillgänglighet för arbetsbelastningens data och system. Segmenteringen mellan komponenter hjälper till att begränsa säkerhetsincidenter till den komprometterade sektionen.

- SE:04 Segmentering
Prestandaeffektivitet hjälper din arbetsbelastning effektivt uppfylla kraven genom optimering av skalning, data och kod. Varje skottvägg kan vara skalbar individuellt för att effektivt uppfylla behoven för uppgiften som är innesluten i skottväggen.

- PE:02 Kapacitetsplanering
- PE:05 Skalning och partitionering

Om detta mönster inför kompromisser inom en pelare bör du överväga dem mot målen för de andra pelarna.

Exempel

Följande Kubernetes-konfigurationsfil skapar en isolerad container för att köra en enda tjänst med sin egen processor, egna minnesresurser och egna gränser.

apiVersion: v1
kind: Pod
metadata:
  name: drone-management
spec:
  containers:
  - name: drone-management-container
    image: drone-service
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "1"

Nästa steg