Share via


Programdesign för verksamhetskritiska arbetsbelastningar i Azure

När du utformar ett program är både funktionella och icke-funktionella programkrav kritiska. Det här designområdet beskriver arkitekturmönster och skalningsstrategier som kan göra ditt program motståndskraftigt mot fel.

Viktigt

Den här artikeln är en del av den verksamhetskritiska arbetsbelastningsserien för Azure Well-Architected Framework . Om du inte är bekant med den här serien rekommenderar vi att du börjar med Vad är en verksamhetskritisk arbetsbelastning?.

Arkitektur för skalningsenhet

Alla funktionella aspekter av en lösning måste kunna skalas för att möta förändringar i efterfrågan. Vi rekommenderar att du använder en skalningsenhetsarkitektur för att optimera skalbarheten från slutpunkt till slutpunkt genom indelning och även för att standardisera processen med att lägga till och ta bort kapacitet. En skalningsenhet är en logisk enhet eller funktion som kan skalas oberoende av varandra. En enhet kan bestå av kodkomponenter, programvärdplattformar, distributionsstämplar som täcker de relaterade komponenterna och till och med prenumerationer för att stödja krav för flera klientorganisationer.

Vi rekommenderar den här metoden eftersom den åtgärdar skalningsgränserna för enskilda resurser och hela programmet. Det hjälper till med komplexa distributions- och uppdateringsscenarier eftersom en skalningsenhet kan distribueras som en enhet. Du kan också testa och verifiera specifika versioner av komponenter i en enhet innan du dirigerar användartrafik till den.

Anta att ditt verksamhetskritiska program är en onlineproduktkatalog. Den har ett användarflöde för bearbetning av produktkommentare och klassificeringar. Flödet använder API:er för att hämta och publicera kommentarer och klassificeringar samt stödkomponenter som en OAuth-slutpunkt, datalager och meddelandeköer. De tillståndslösa API-slutpunkterna representerar detaljerade funktionella enheter som måste anpassas till ändringar på begäran. Den underliggande programplattformen måste också kunna skalas därefter. För att undvika flaskhalsar i prestanda måste även underordnade komponenter och beroenden skalas i lämplig grad. De kan antingen skala oberoende av varandra, som separata skalningsenheter eller tillsammans som en del av en enda logisk enhet.

Exempel på skalningsenheter

Följande bild visar möjliga omfång för skalningsenheter. Omfången sträcker sig från mikrotjänstpoddar till klusternoder och regionala distributionsstämplar.

Diagram som visar flera omfång för skalningsenheter.

Designöverväganden

  • Omfång. Omfånget för en skalningsenhet, relationen mellan skalningsenheter och deras komponenter bör definieras enligt en kapacitetsmodell. Ta hänsyn till icke-funktionella prestandakrav.

  • Skalningsgränser. Skalningsgränser och kvoter för Azure-prenumerationer kan ha betydelse för programdesign, teknikval och definitionen av skalningsenheter. Skalningsenheter kan hjälpa dig att kringgå skalningsgränserna för en tjänst. Om ett AKS-kluster i en enhet till exempel bara kan ha 1 000 noder kan du använda två enheter för att öka gränsen till 2 000 noder.

  • Förväntad belastning. Använd antalet begäranden för varje användarflöde, förväntad högsta begärandefrekvens (begäranden per sekund) och dagliga/veckovisa/säsongsbaserade trafikmönster för att informera kärnskalningskraven. Ta också hänsyn till de förväntade tillväxtmönstren för både trafik och datavolym.

  • Acceptabel försämrad prestanda. Fastställ om en degraderad tjänst med höga svarstider är acceptabel under belastning. När du modellerar den kapacitet som krävs är den nödvändiga prestandan för lösningen under belastning en viktig faktor.

  • Icke-funktionella krav. Tekniska scenarier och affärsscenarier har olika överväganden för motståndskraft, tillgänglighet, svarstid, kapacitet och observerbarhet. Analysera dessa krav i kontexten för viktiga användarflöden från slutpunkt till slutpunkt. Du har relativ flexibilitet när det gäller design, beslutsfattande och teknikval på användarflödesnivå.

Designrekommendationer

  • Definiera omfånget för en skalningsenhet och de gränser som utlöser den enhet som ska skalas.

  • Se till att alla programkomponenter kan skalas oberoende eller som en del av en skalningsenhet som innehåller andra relaterade komponenter.

  • Definiera relationen mellan skalningsenheter baserat på en kapacitetsmodell och icke-funktionella krav.

  • Definiera en regional distributionsstämpel för att förena etablering, hantering och drift av regionala programresurser i en heterogen men beroende skalningsenhet. När belastningen ökar kan extra stämplar distribueras, inom samma Azure-region eller olika, för att horisontellt skala lösningen.

  • Använd en Azure-prenumeration som skalningsenhet så att skalningsgränser inom en enskild prenumeration inte begränsar skalbarheten. Den här metoden gäller för storskaliga programscenarier som har betydande trafikvolym.

  • Modell krävs kapacitet runt identifierade trafikmönster för att se till att tillräcklig kapacitet etableras vid tider med hög belastning för att förhindra tjänstförsämring. Du kan också optimera kapaciteten under tider med låg belastning.

  • Mät den tid som krävs för att utföra utskalnings- och inskalningsåtgärder för att säkerställa att de naturliga variationerna i trafiken inte skapar en oacceptabel tjänstförsämringsnivå. Spåra varaktigheten för skalningsåtgärden som ett driftmått.

Anteckning

När du distribuerar i en Azure-landningszon kontrollerar du att landningszonprenumerationen är dedikerad till programmet för att tillhandahålla en tydlig hanteringsgräns och för att undvika antimönstret Noisy Neighbor.

Global distribution

Det är omöjligt att undvika fel i en mycket distribuerad miljö. Det här avsnittet innehåller strategier för att åtgärda många felscenarier. Programmet måste kunna hantera regionala och zonindeliga fel. Den måste distribueras i en aktiv/aktiv modell så att belastningen distribueras mellan alla regioner.

Titta på den här videon för att få en översikt över hur du planerar för fel i verksamhetskritiska program och maximerar återhämtning:

Designöverväganden

  • Redundans. Programmet måste distribueras till flera regioner. Inom en region rekommenderar vi dessutom starkt att du använder tillgänglighetszoner för att tillåta feltolerans på datacenternivå. Tillgänglighetszoner har en svarstidsperimeter på mindre än 2 millisekunder mellan tillgänglighetszoner. För arbetsbelastningar som är "trafikintensiva" mellan zoner kan den här svarstiden medföra en prestandaavgift och medföra bandbreddsavgifter för dataöverföring mellan zoner.

  • Aktiv/aktiv modell. En aktiv/aktiv distributionsstrategi rekommenderas eftersom den maximerar tillgängligheten och ger ett högre sammansatt serviceavtal (SLA). Det kan dock medföra utmaningar kring datasynkronisering och konsekvens för många programscenarier. Hantera utmaningarna på dataplattformsnivå samtidigt som du överväger kompromisserna med ökade kostnader och tekniska insatser.

    En aktiv/aktiv distribution mellan flera molnleverantörer är ett sätt att potentiellt minska beroendet av globala resurser inom en enda molnleverantör. En aktiv/aktiv distributionsstrategi för flera moln medför dock en betydande komplexitet kring CI/CD. Med tanke på skillnaderna i resursspecifikationer och funktioner mellan molnleverantörer behöver du också särskilda distributionsstämplar för varje moln.

  • Geografisk fördelning. Arbetsbelastningen kan ha efterlevnadskrav för geografisk dataplacering, dataskydd och datakvarhållning. Överväg om det finns specifika regioner där data måste finnas eller var resurser måste distribueras.

  • Begärande ursprung. Användarnas eller beroende systemens geografiska närhet och densitet bör ligga till hjälp vid designbeslut om global distribution.

  • Anslutning. Hur arbetsbelastningen används av användare eller externa system påverkar din design. Överväg om programmet är tillgängligt via det offentliga Internet eller privata nätverk som använder VPN- eller Azure ExpressRoute-kretsar.

Designrekommendationer och konfigurationsalternativ på plattformsnivå finns i Programplattform: Global distribution.

Löst kopplad händelsedriven arkitektur

Koppling möjliggör kommunikation mellan tjänster via väldefinierade gränssnitt. En lös koppling gör att en applikationskomponent kan fungera oberoende av varandra. En arkitekturstil för mikrotjänster är konsekvent med verksamhetskritiska krav. Det underlättar hög tillgänglighet genom att förhindra sammanhängande fel.

För lös koppling rekommenderar vi starkt att du använder händelsedriven design. Asynkron meddelandebearbetning via en mellanhand kan skapa återhämtning.

Diagram som illustrerar asynkron händelsedriven kommunikation.

I vissa scenarier kan program kombinera lös och nära koppling, beroende på affärsmål.

Designöverväganden

  • Körningsberoenden. Löst kopplade tjänster bör inte begränsas till att använda samma beräkningsplattform, programmeringsspråk, körning eller operativsystem.

  • Skalning. Tjänsterna ska kunna skalas oberoende av varandra. Optimera användningen av infrastruktur- och plattformsresurser.

  • Feltolerans. Fel bör hanteras separat och bör inte påverka klienttransaktioner.

  • Transaktionsintegritet. Överväg effekten av dataskapande och beständighet som sker i separata tjänster.

  • Distribuerad spårning. Spårning från slutpunkt till slutpunkt kan kräva komplex orkestrering.

Designrekommendationer

  • Justera mikrotjänstgränserna med kritiska användarflöden.

  • Använd händelsedriven asynkron kommunikation där det är möjligt för att stödja hållbar skalning och optimala prestanda.

  • Använd mönster som Outbox och Transactional Session för att garantera konsekvens så att varje meddelande bearbetas korrekt.

Exempel: Händelsedriven metod

Referensimplementeringen Mission-Critical Online använder mikrotjänster för att bearbeta en enda affärstransaktion. Den tillämpar skrivåtgärder asynkront med en asynkron meddelandekö och arbetare. Läsåtgärder är synkrona, och resultatet returneras direkt till anroparen.

Diagram som visar händelsedriven kommunikation.

Återhämtningsmönster och felhantering i programkod

Ett verksamhetskritiskt program måste vara utformat för att vara motståndskraftigt så att det hanterar så många felscenarier som möjligt. Den här återhämtningsförmågan maximerar tjänstens tillgänglighet och tillförlitlighet. Programmet bör ha självåterställningsfunktioner som du kan implementera med hjälp av designmönster som Återförsök med backoff och kretsbrytare.

För icke-tillfälliga fel som du inte kan minimera helt i programlogik måste hälsomodellen och driftomslutningarna vidta korrigerande åtgärder. Programkoden måste innehålla rätt instrumentation och loggning för att informera hälsomodellen och underlätta efterföljande felsökning eller rotorsaksanalys efter behov. Du måste implementera distribuerad spårning för att ge anroparen ett omfattande felmeddelande som innehåller ett korrelations-ID när ett fel inträffar.

Verktyg som Application Insights kan hjälpa dig att fråga, korrelera och visualisera programspårningar.

Designöverväganden

  • Rätt konfigurationer. Det är inte ovanligt att tillfälliga problem orsakar sammanhängande fel. Om du till exempel försöker igen utan lämplig backoff förvärras problemet när en tjänst begränsas. Du kan fördröja återförsök linjärt eller öka dem exponentiellt för att backa genom växande fördröjningar.

  • Hälsoslutpunkter. Du kan exponera funktionella kontroller i programkoden med hjälp av hälsoslutpunkter som externa lösningar kan avsöka för att hämta hälsostatus för programkomponenten.

Designrekommendationer

Här följer några vanliga programvaruutvecklingsmönster för motståndskraftiga program:

Mönster Sammanfattning
Köbaserad belastningsutjämning Introducerar en buffert mellan konsumenter och begärda resurser för att säkerställa konsekventa belastningsnivåer. När konsumentbegäranden placeras i kö hanterar en arbetsprocess dem mot den begärda resursen i en takt som anges av arbetaren och av den begärda resursens möjlighet att bearbeta begärandena. Om konsumenterna förväntar sig svar på sina begäranden måste du implementera en separat svarsmekanism. Tillämpa en prioriterad ordning så att de viktigaste aktiviteterna utförs först.
Kretsbrytare Ger stabilitet genom att antingen vänta på återställning eller snabbt avvisa begäranden i stället för att blockera i väntan på en otillgänglig fjärrtjänst eller resurs. Det här mönstret hanterar också fel som kan ta varierande tid att återställa från när en anslutning görs till en fjärrtjänst eller resurs.
Bulkhead Försök att partitionera tjänstinstanser i grupper baserat på belastnings- och tillgänglighetskrav, isolera fel för att upprätthålla tjänstfunktioner.
Saga Hanterar datakonsekvens mellan mikrotjänster som har oberoende datalager genom att se till att tjänsterna uppdaterar varandra via definierade händelse- eller meddelandekanaler. Varje tjänst utför lokala transaktioner för att uppdatera sitt eget tillstånd och publicerar en händelse för att utlösa nästa lokala transaktion i sagan. Om en tjänstuppdatering misslyckas kör sagan kompenserande transaktioner för att motverka föregående tjänstuppdateringssteg. Enskilda tjänstuppdateringssteg kan själva implementera återhämtningsmönster, till exempel återförsök.
Övervakning av slutpunktshälsa Implementerar funktionskontroller i ett program som externa verktyg kan komma åt via exponerade slutpunkter med jämna mellanrum. Du kan tolka svar från slutpunkterna med hjälp av viktiga driftmått för att informera om programmets hälsa och utlösa driftsvar, till exempel att skapa en avisering eller utföra en kompenserande återställningsdistribution.
Försök igen Hanterar tillfälliga fel elegant och transparent.
- Avbryt om felet sannolikt inte är tillfälligt och sannolikt inte kommer att lyckas om åtgärden görs igen.
– Försök igen om felet är ovanligt eller ovanligt och åtgärden sannolikt kommer att lyckas om det görs ett nytt försök omedelbart.
– Försök igen efter en fördröjning om felet orsakas av ett villkor som kan behöva en kort tid att återställa, till exempel nätverksanslutning eller fel med hög belastning. Tillämpa en lämplig backoff-strategi när fördröjningarna för återförsök ökar.
Begränsning Styr förbrukningen av resurser som används av programkomponenter och skyddar dem från att bli överbelastade. När en resurs når ett belastningströskelvärde skjuter den upp åtgärder med lägre prioritet och försämrar icke-nödvändiga funktioner så att viktiga funktioner kan fortsätta tills det finns tillräckligt med resurser för att återgå till normal drift.

Här följer några ytterligare rekommendationer:

  • Använd SDK:er som tillhandahålls av leverantören, till exempel Azure SDK:er, för att ansluta till beroende tjänster. Använd inbyggda återhämtningsfunktioner i stället för att implementera anpassade funktioner.

  • Använd en lämplig backoff-strategi vid återförsök av misslyckade beroendeanrop för att undvika ett självförvållat DDoS-scenario.

  • Definiera vanliga tekniska kriterier för alla programmikrotjänstteam för att öka konsekvensen och hastigheten vid användning av återhämtningsmönster på programnivå.

  • Implementera återhämtningsmönster med hjälp av beprövade standardiserade paket, till exempel Polly för C# eller Sentinel för Java.

  • Använd korrelations-ID:t för alla spårningshändelser och loggmeddelanden för att länka dem till en viss begäran. Returnera korrelations-ID:t till anroparen för alla anrop, inte bara misslyckade begäranden.

  • Använd strukturerad loggning för alla loggmeddelanden. Välj en enhetlig datamottagare för programspårningar, mått och loggar så att operatörer enkelt kan felsöka problem. Mer information finns i Samla in, aggregera och lagra övervakningsdata för molnprogram.

  • Se till att driftdata används tillsammans med affärskrav för att informera en programhälsomodell.

Val av programmeringsspråk

Det är viktigt att välja rätt programmeringsspråk och ramverk. Dessa beslut drivs ofta av kompetensuppsättningar eller standardiserade tekniker i organisationen. Det är dock viktigt att utvärdera prestanda, motståndskraft och övergripande funktioner för olika språk och ramverk.

Designöverväganden

  • Funktioner i Development Kit. Det finns skillnader i de funktioner som erbjuds av Azure-tjänst-SDK:er på olika språk. Dessa skillnader kan påverka ditt val av En Azure-tjänst eller ett programmeringsspråk. Om Azure Cosmos DB till exempel är ett genomförbart alternativ kanske Go inte är ett lämpligt utvecklingsspråk eftersom det inte finns någon SDK från första part.

  • Funktionsuppdateringar. Överväg hur ofta SDK:n uppdateras med nya funktioner för det valda språket. Vanliga SDK:er, till exempel .NET- och Java-bibliotek, uppdateras ofta. Andra SDK:er eller SDK:er för andra språk kan uppdateras mindre ofta.

  • Flera programmeringsspråk eller ramverk. Du kan använda flera tekniker för att stödja olika sammansatta arbetsbelastningar. Du bör dock undvika spridning eftersom det medför hanteringskomplexitet och driftsutmaningar.

  • Beräkningsalternativ. Äldre eller upphovsrättsskyddad programvara kanske inte körs i PaaS-tjänster. Du kanske inte heller kan inkludera äldre eller egenutvecklad programvara i containrar.

Designrekommendationer

  • Utvärdera alla relevanta Azure SDK:er för de funktioner du behöver och dina valda programmeringsspråk. Kontrollera justeringen med icke-funktionella krav.

  • Optimera valet av programmeringsspråk och ramverk på mikrotjänstnivå. Använd flera tekniker efter behov.

  • Prioritera .NET SDK för att optimera tillförlitlighet och prestanda. .NET Azure SDK:er ger vanligtvis fler funktioner och uppdateras ofta.

Nästa steg

Granska övervägandena för programplattformen.