Patroon Consolidatie van berekenbronnen

Consolideer meerdere taken of bewerkingen in een enkele rekenkundige eenheid. Dit kan het gebruik van berekenbronnen verhogen en de kosten en beheeroverhead verminderen die zijn gekoppeld aan het uitvoeren van berekenverwerkingen in cloudtoepassingen.

Context en probleem

Een cloudtoepassing implementeert vaak tal van bewerkingen. In sommige oplossingen is het in eerste instantie zinvol om het ontwerpprincipe van scheiding van problemen te volgen en deze bewerkingen te verdelen in afzonderlijke rekenkundige eenheden die afzonderlijk worden gehost en geïmplementeerd (bijvoorbeeld als afzonderlijke App Service Web Apps, afzonderlijke virtuele machines of afzonderlijke cloudservicerollen). Hoewel deze strategie het logische ontwerp van de oplossing vereenvoudigt, kan de implementatie van een groot aantal rekenkundige eenheden als onderdeel van dezelfde toepassing echter runtime-hostingkosten verhogen en het beheer van het systeem complexer maken.

De afbeelding toont een voorbeeld van een vereenvoudigde structuur van een cloudoplossing die wordt geïmplementeerd met meer dan één rekenkundige eenheid. Elke rekenkundige eenheid wordt uitgevoerd in een eigen virtuele omgeving. Elke functie is als een afzonderlijke taak geïmplementeerd (met de naam Taak A tot en met Taak E) die wordt uitgevoerd in een eigen rekenkundige eenheid.

Taken uitvoeren in een cloudomgeving met een reeks specifieke rekenkundige eenheden

Elke rekenkundige eenheid verbruikt toerekenbare resources, zelfs wanneer deze niet-actief is of weinig wordt gebruikt. Daarom is dit niet altijd de meest rendabele oplossing.

In Azure geldt dit probleem voor rollen in een cloudservice, App Services en virtuele machines. Deze items worden in hun eigen virtuele omgeving uitgevoerd. Als u een verzameling van afzonderlijke rollen, websites of virtuele machines uitvoert die zijn ontworpen om een reeks goed gedefinieerde bewerkingen uit te voeren, maar die moeten communiceren en samenwerken als onderdeel van een enkele oplossing, kan dit een inefficiënt gebruik van resources zijn.

Oplossing

Het is mogelijk om meerdere taken of bewerkingen in een enkele rekenkundige eenheid te consolideren om de kosten te verlagen, gebruik te vergroten, communicatiesnelheid te verbeteren en beheer te beperken.

Taken kunnen worden gegroepeerd volgens de criteria op basis van de functies die door de omgeving zijn opgegeven en de kosten die zijn gekoppeld aan deze functies. Een veelgebruikte aanpak is om te zoeken naar taken die een vergelijkbaar profiel hebben met betrekking tot hun schaalbaarheid, levensduur en verwerkingsvereisten. Als u deze groepeert, kunnen ze als een eenheid worden geschaald. Door de flexibiliteit van veel cloudomgevingen kunnen extra exemplaren van een rekenkundige eenheid worden gestart en gestopt volgens de werkbelasting. Azure biedt bijvoorbeeld automatisch schalen, dat u kunt toepassen op rollen in een cloudservice, App Services en virtuele machines. Zie voor meer informatie Richtlijnen voor automatisch schalen.

Schaalbaarheid kan echter ook worden gebruikt om te bepalen welke bewerkingen niet moeten worden gegroepeerd. Neem bijvoorbeeld de volgende twee taken:

  • Taak 1 peilt incidentele, tijdongevoelige berichten die naar een wachtrij worden verzonden.
  • Taak 2 verwerkt hoge pieken in netwerkverkeer.

De tweede taak vereist flexibiliteit waarbij gebruik kan worden gemaakt van het starten en stoppen van een groot aantal exemplaren van de rekenkundige eenheid. Het toepassen van dezelfde schaal op de eerste taak zal simpelweg resulteren in meer taken die luisteren naar incidentele berichten in dezelfde wachtrij. Dit is een verspilling van resources.

In veel cloudomgevingen is het mogelijk om de resources op te geven die voor een rekenkundige eenheid beschikbaar zijn met betrekking tot het aantal CPU-kernen, het geheugen, de schijfruimte enzovoort. In het algemeen geldt hoe meer resources er zijn opgegeven, hoe hoger de kosten zijn. Als u geld wilt besparen, is het belangrijk om het werk dat een dure rekenkundige eenheid uitvoert te maximaliseren en deze niet voor een langere periode inactief te laten zijn.

Als er taken zijn die veel CPU-energie in korte pieken nodig hebben, overweeg deze dan in één rekenkundige eenheid te consolideren die de benodigde energie levert. Het is echter belangrijk dat u deze behoefte om dure resources bezig te houden en conflicten die kunnen optreden als deze overbelast raken in evenwicht houdt. Langlopende, rekenintensieve taken mogen bijvoorbeeld niet dezelfde rekenkundige eenheid delen.

Problemen en overwegingen

Houd rekening met de volgende punten bij het implementeren van dit patroon:

Schaalbaarheid en elasticiteit. Veel cloudoplossingen implementeren schaalbaarheid en flexibiliteit op het niveau van de rekenkundige eenheid door exemplaren van eenheden te starten en te stoppen. Voorkom dat u taken die conflicterende schaalbaarheidsvereisten hebben in dezelfde rekenkundige eenheid groepeert.

Levensduur. De cloudinfrastructuur recyclet periodiek de virtuele omgeving die als host fungeert voor een rekenkundige eenheid. Wanneer er veel langlopende taken binnen een rekenkundige eenheid worden uitgevoerd, kan het noodzakelijk zijn om de eenheid te configureren om te voorkomen dat deze wordt gerecycled totdat deze taken zijn voltooid. U kunt de taken ook ontwerpen met behulp van een benadering waarbij op punten wordt gecontroleerd, waardoor ze foutloos stoppen en verdergaan vanaf het punt waarop ze zijn onderbroken wanneer de rekenkundige eenheid opnieuw wordt gestart.

Vrijgeeffrequentie. Als de implementatie of configuratie van een taak regelmatig wijzigt, kan het nodig zijn om de rekenkundige eenheid die als host fungeert voor de bijgewerkte code te stoppen, opnieuw te configureren en de eenheid opnieuw te implementeren en vervolgens opnieuw te starten. Dit proces vereist ook dat alle andere taken binnen dezelfde rekenkundige eenheid worden gestopt, opnieuw worden geïmplementeerd en opnieuw worden gestart.

Beveiliging. Taken in dezelfde rekenkundige eenheid delen mogelijk dezelfde beveiligingscontext en hebben toegang tot dezelfde resources. Er moet een hoge mate van vertrouwen zijn tussen de taken en vertrouwen dat één taak niet wordt beschadigd of een negatieve invloed op een andere taak heeft. Daarnaast vergroot een toename van het aantal taken die in een rekenkundige eenheid worden uitgevoerd de kwetsbaarheid voor aanvallen van de eenheid. Elke taak is net zo veilig als de taak met de meeste beveiligingsproblemen.

Fouttolerantie. Als één taak in een rekenkundige eenheid mislukt of zich abnormaal gedraagt, kan deze invloed hebben op de andere taken die binnen dezelfde eenheid worden uitgevoerd. Als één taak bijvoorbeeld niet correct wordt gestart, kan dit ertoe leiden dat de hele opstartlogica voor de rekenkundige eenheid mislukt en voorkomt dat andere taken in dezelfde eenheid worden uitgevoerd.

Conflicten. Vermijd conflicten tussen taken die concurreren voor resources in dezelfde rekenkundige eenheid. Taken die dezelfde rekenkundige eenheid delen, moeten in het ideale geval andere kenmerken van resourcegebruik vertonen. Twee rekenintensieve taken moeten zich bijvoorbeeld niet in dezelfde rekenkundige eenheid bevinden. Hetzelfde geldt voor twee taken die grote hoeveelheden geheugen gebruiken. Het combineren van een rekenintensieve taak met een taak die een grote hoeveelheid geheugen vereist, is echter een werkbare combinatie.

Notitie

Overweeg om rekenbronnen alleen te consolideren voor een systeem dat al een bepaalde tijd in productie is, zodat operators en ontwikkelaars het systeem kunnen bewaken en een heatmap kunnen maken die aangeeft hoe elke taak verschillende resources gebruikt. Deze heatmap kan worden gebruikt om te bepalen welke taken goede kandidaten zijn voor het delen van rekenresources.

Complexiteit. De combinatie van meerdere taken in één rekenkundige eenheid voegt complexiteit toe aan de code in de eenheid. Hierdoor wordt het mogelijk moeilijker om te testen, fouten op te sporen en te onderhouden.

Stabiele logische architectuur. Ontwerp en implementeer de code in elke taak, zodat deze niet hoeft te wijzigen, zelfs wanneer de fysieke omgeving waarin de taak wordt uitgevoerd, wijzigt.

Andere strategieën. Het consolideren van rekenresources is slechts één manier om de kosten met betrekking tot meerdere taken die gelijktijdig worden uitgevoerd te verlagen. Dit vereist een zorgvuldige planning en bewaking om ervoor te zorgen dat dit een effectieve aanpak blijft. Andere strategieën zijn mogelijk meer geschikt. Dit is afhankelijk van de aard van het werk en waar de gebruikers die deze taken uitvoeren zich bevinden. De functionele ontleding van de werkbelasting (zoals is beschreven in de Compute Partitioning Guidance (Richtlijnen voor berekenpartitionering)) bijvoorbeeld is misschien een betere optie.

Wanneer dit patroon gebruiken

Gebruik dit patroon voor taken die niet rendabel zijn als ze worden uitgevoerd in hun eigen rekenkundige eenheden. Als een taak vaak niet-actief is, kan het uitvoeren van deze taak in een toegewezen eenheid kostbaar zijn.

Dit patroon is mogelijk niet geschikt voor taken die kritieke fouttolerante bewerkingen uitvoeren of taken die uiterst gevoelige of persoonlijke gegevens verwerken en hun eigen beveiligingscontext vereisen. Deze taken moeten in hun eigen geïsoleerde omgeving worden uitgevoerd in een afzonderlijke rekenkundige eenheid.

Voorbeeld

Als u een cloudservice in Azure maakt, is het mogelijk om de verwerking die door meerdere taken wordt uitgevoerd in één rol te consolideren. Dit is doorgaans een werkrol die achtergrond- of asynchrone verwerkingstaken uitvoert.

Het is in sommige gevallen mogelijk om achtergrond- of asynchrone verwerkingstaken in de webrol op te nemen. Deze techniek helpt de kosten te verlagen en implementatie te vereenvoudigen, hoewel deze invloed kan hebben op de schaalbaarheid en reactietijd van de openbare interface die door de webrol wordt geleverd.

De rol is verantwoordelijk voor het starten en stoppen van de taken. Wanneer de Azure-infrastructuurcontroller een rol laadt, wordt de Start-gebeurtenis voor de rol gegenereerd. U kunt de OnStart-methode van de WebRole- of WorkerRole-klasse overschrijven om deze gebeurtenis af te handelen, bijvoorbeeld om de gegevens en andere resources waar de taken in deze methode van afhankelijk zijn te initialiseren.

Wanneer de OnStart methode is voltooid, kan de rol beginnen te reageren op aanvragen. U vindt meer informatie en richtlijnen over het gebruik van de OnStart- en Run-methoden in een rol in de sectie Application Startup Processes (Opstartprocessen van toepassingen) in de patronen- en procedureshandleiding Moving Applications to the Cloud (Toepassingen naar de cloud verplaatsen).

Houd de code in de OnStart-methode zo beknopt mogelijk. Azure legt geen limiet op voor de tijd die nodig is om deze methode te voltooien, maar de rol kan niet reageren op netwerkaanvragen die worden ontvangen, totdat deze methode is voltooid.

Wanneer de OnStart-methode is voltooid, voert de rol de Run-methode uit. Vanaf dat moment kan de infrastructuurcontroller beginnen met het verzenden van aanvragen naar de rol.

Plaats de code die daadwerkelijk de taken maakt in de Run-methode. Houd er rekening mee dat de Run-methode de levensduur van de rolinstantie definieert. Wanneer deze methode is voltooid, zorgt de infrastructuurcontroller ervoor dat de rol wordt afgesloten.

Wanneer een rol wordt afgesloten of wordt gerecycled, voorkomt de infrastructuurcontroller dat er inkomende aanvragen worden ontvangen van de load balancer en genereert deze de Stop-gebeurtenis. U kunt deze gebeurtenis vastleggen door de OnStop-methode van de rol te overschrijven en eventuele vereiste opschoonwerkzaamheden uit te voeren voordat de rol wordt beëindigd.

Alle acties die in de OnStop-methode worden uitgevoerd, moeten binnen vijf minuten (of 30 seconden als u de Azure-emulator op een lokale computer gebruikt) worden voltooid. Anders gaat de Azure-infrastructuurcontroller ervan uit dat de rol tot stilstand is gekomen en wordt de rol geforceerd gestopt.

De taken worden door de Run-methode gestart die wacht tot de taken zijn voltooid. De taken implementeren de bedrijfslogica van de cloudservice en kunnen reageren op berichten die op de rol worden gepost via de load balancer van Azure. De afbeelding toont de levenscyclus van taken en resources in een rol in een Azure-cloudservice.

De levenscyclus van taken en resources in een rol in een Azure-cloudservice

Het WorkerRole.cs-bestand in het ComputeResourceConsolidation.Worker-project toont een voorbeeld van hoe u dit patroon in een Azure-cloudservice kunt implementeren.

Het ComputeResourceConsolidation.Worker-project maakt deel uit van de ComputeResourceConsolidation-oplossing. Deze kunt u via GitHub downloaden.

De MyWorkerTask1- en de MyWorkerTask2-methoden laten zien hoe u verschillende taken binnen dezelfde werkrol kunt uitvoeren. De volgende code geeft MyWorkerTask1 weer. Dit is een eenvoudige taak die gedurende 30 seconden inactief is en vervolgens een traceringsbericht uitvoert. Dit proces wordt herhaald totdat de taak is geannuleerd. De code in MyWorkerTask2 is vergelijkbaar.

// A sample worker role task.
private static async Task MyWorkerTask1(CancellationToken ct)
{
  // Fixed interval to wake up and check for work and/or do work.
  var interval = TimeSpan.FromSeconds(30);

  try
  {
    while (!ct.IsCancellationRequested)
    {
      // Wake up and do some background processing if not canceled.
      // TASK PROCESSING CODE HERE
      Trace.TraceInformation("Doing Worker Task 1 Work");

      // Go back to sleep for a period of time unless asked to cancel.
      // Task.Delay will throw an OperationCanceledException when canceled.
      await Task.Delay(interval, ct);
    }
  }
  catch (OperationCanceledException)
  {
    // Expect this exception to be thrown in normal circumstances or check
    // the cancellation token. If the role instances are shutting down, a
    // cancellation request will be signaled.
    Trace.TraceInformation("Stopping service, cancellation requested");

    // Rethrow the exception.
    throw;
  }
}

De voorbeeldcode toont een algemene implementatie van een achtergrondproces. In een werkelijke toepassing kunt u dezelfde structuur volgen. U moet alleen wel uw eigen verwerkingslogica in de hoofdtekst van de lus plaatsen die wacht op de annuleringsaanvraag.

Nadat de werkrol de resources die worden gebruikt heeft geïnitialiseerd, start de Run-methode de twee taken gelijktijdig, zoals hier wordt weergegeven.

/// <summary>
/// The cancellation token source use to cooperatively cancel running tasks
/// </summary>
private readonly CancellationTokenSource cts = new CancellationTokenSource();

/// <summary>
/// List of running tasks on the role instance
/// </summary>
private readonly List<Task> tasks = new List<Task>();

// RoleEntry Run() is called after OnStart().
// Returning from Run() will cause a role instance to recycle.
public override void Run()
{
  // Start worker tasks and add to the task list
  tasks.Add(MyWorkerTask1(cts.Token));
  tasks.Add(MyWorkerTask2(cts.Token));

  foreach (var worker in this.workerTasks)
  {
      this.tasks.Add(worker);
  }

  Trace.TraceInformation("Worker host tasks started");
  // The assumption is that all tasks should remain running and not return,
  // similar to role entry Run() behavior.
  try
  {
    Task.WaitAll(tasks.ToArray());
  }
  catch (AggregateException ex)
  {
    Trace.TraceError(ex.Message);

    // If any of the inner exceptions in the aggregate exception
    // are not cancellation exceptions then re-throw the exception.
    ex.Handle(innerEx => (innerEx is OperationCanceledException));
  }

  // If there wasn't a cancellation request, stop all tasks and return from Run()
  // An alternative to canceling and returning when a task exits would be to
  // restart the task.
  if (!cts.IsCancellationRequested)
  {
    Trace.TraceInformation("Task returned without cancellation request");
    Stop(TimeSpan.FromMinutes(5));
  }
}
...

In dit voorbeeld wacht de Run-methode tot taken worden voltooid. Als een taak wordt geannuleerd, gaat de Run-methode ervan uit dat de rol wordt afgesloten en wacht deze tot de resterende taken worden geannuleerd, voordat de bewerking wordt beëindigd (wat na maximaal vijf minuten gebeurt). Als een taak mislukt als gevolg van een verwachte uitzondering, annuleert de Run-methode de taak.

U kunt uitgebreidere bewakingsstrategieën en afhandelingsstrategieën voor uitzonderingen in de Run-methode implementeren, zoals mislukte taken opnieuw starten of code opnemen waarmee de rol kan worden gestopt en afzonderlijke taken worden gestart.

De Stop-methode die in de volgende code wordt weergegeven, wordt aangeroepen wanneer de infrastructuurcontroller de rolinstantie afsluit (deze wordt vanuit de OnStop-methode aangeroepen). De code stopt elke taak probleemloos door deze te annuleren. Als het langer dan vijf minuten duurt voordat een taak wordt voltooid, wacht de annuleringsverwerking in de Stop-methode niet langer en wordt de rol beëindigd.

// Stop running tasks and wait for tasks to complete before returning
// unless the timeout expires.
private void Stop(TimeSpan timeout)
{
  Trace.TraceInformation("Stop called. Canceling tasks.");
  // Cancel running tasks.
  cts.Cancel();

  Trace.TraceInformation("Waiting for canceled tasks to finish and return");

  // Wait for all the tasks to complete before returning. Note that the
  // emulator currently allows 30 seconds and Azure allows five
  // minutes for processing to complete.
  try
  {
    Task.WaitAll(tasks.ToArray(), timeout);
  }
  catch (AggregateException ex)
  {
    Trace.TraceError(ex.Message);

    // If any of the inner exceptions in the aggregate exception
    // are not cancellation exceptions then rethrow the exception.
    ex.Handle(innerEx => (innerEx is OperationCanceledException));
  }
}

De volgende patronen en richtlijnen zijn mogelijk ook relevant bij de implementatie van dit patroon:

  • Richtlijnen voor automatisch schalen. Automatisch schalen kan worden gebruikt om exemplaren van service gehoste rekenkundige resources te starten en stoppen, afhankelijk van de verwachte vraag voor verwerking.

  • Richtlijnen voor het partitioneren van berekeningen. Hierin wordt beschreven hoe u de services en onderdelen in een cloudservice kunt toewijzen op een manier die doorlopende kosten minimaliseert en tegelijkertijd de schaalbaarheid, prestaties, beschikbaarheid en beveiliging van de service behoudt.

  • Dit patroon bevat een voorbeeldtoepassing die u kunt downloaden.