Taakafhankelijkheden maken om taken uit te voeren die afhankelijk zijn van andere taken

Met Batch-taakafhankelijkheden maakt u taken die zijn gepland voor uitvoering op rekenknooppunten nadat een of meer bovenliggende taken zijn voltooid. U kunt bijvoorbeeld een taak maken waarmee elk frame van een 3D-film wordt weergegeven met afzonderlijke, parallelle taken. De laatste taak voegt de weergegeven frames pas samen in de volledige film nadat alle frames zijn weergegeven. Met andere woorden, de laatste taak is afhankelijk van de vorige bovenliggende taken.

Enkele scenario's waarin taakafhankelijkheden nuttig zijn, zijn:

  • Werkbelastingen in MapReduce-stijl in de cloud.
  • Taken waarvan gegevensverwerkingstaken kunnen worden uitgedrukt als een gerichte acyclische grafiek (DAG).
  • Processen voor pre-rendering en post-rendering, waarbij elke taak moet worden voltooid voordat de volgende taak kan beginnen.
  • Elke andere taak waarin downstreamtaken afhankelijk zijn van de uitvoer van upstream-taken.

Afhankelijke taken worden standaard pas gepland voor uitvoering nadat de bovenliggende taak is voltooid. U kunt eventueel een afhankelijkheidsactie opgeven om het standaardgedrag te overschrijven en de afhankelijke taak uit te voeren, zelfs als de bovenliggende taak mislukt.

In dit artikel wordt besproken hoe u taakafhankelijkheden configureert met behulp van de Batch .NET-bibliotheek . We laten eerst zien hoe u taakafhankelijkheid van uw taken inschakelt en vervolgens laten we zien hoe u een taak met afhankelijkheden configureert. We beschrijven ook hoe u een afhankelijkheidsactie opgeeft om afhankelijke taken uit te voeren als het bovenliggende item mislukt. Ten slotte bespreken we de afhankelijkheidsscenario's die Door Batch worden ondersteund.

Taakafhankelijkheden inschakelen

Als u taakafhankelijkheden wilt gebruiken in uw Batch-toepassing, moet u de taak eerst configureren voor het gebruik van taakafhankelijkheden. Schakel het in Batch .NET in op uw CloudJob door de eigenschap UsesTaskDependencies in te stellen op true:

CloudJob unboundJob = batchClient.JobOperations.CreateJob( "job001",
    new PoolInformation { PoolId = "pool001" });

// IMPORTANT: This is REQUIRED for using task dependencies.
unboundJob.UsesTaskDependencies = true;

In het voorgaande codefragment is 'batchClient' een exemplaar van de klasse BatchClient .

Afhankelijke taken maken

Als u een taak wilt maken die afhankelijk is van de voltooiing van een of meer bovenliggende taken, kunt u opgeven dat de taak 'afhankelijk' is van de andere taken. Configureer in Batch .NET de eigenschap CloudTask.DependsOn met een exemplaar van de klasse TaskDependencies :

// Task 'Flowers' depends on completion of both 'Rain' and 'Sun'
// before it is run.
new CloudTask("Flowers", "cmd.exe /c echo Flowers")
{
    DependsOn = TaskDependencies.OnIds("Rain", "Sun")
},

Met dit codefragment maakt u een afhankelijke taak met taak-id 'Bloemen'. De taak 'Bloemen' is afhankelijk van de taken 'Regen' en 'Zon'. Taak 'Bloemen' wordt alleen gepland om te worden uitgevoerd op een rekenknooppunt nadat de taken 'Regen' en 'Zon' zijn voltooid.

Notitie

Een taak wordt standaard beschouwd als voltooid wanneer deze de status Voltooid heeft en de afsluitcode is 0. In Batch .NET betekent dit dat de eigenschapswaarde CloudTask.State is Completed en dat de eigenschapswaarde TaskExecutionInformation.ExitCode van CloudTask is 0. Zie de sectie Afhankelijkheidsacties voor meer informatie over het wijzigen hiervan.

Afhankelijkheidsscenario's

Er zijn drie basisscenario's voor taakafhankelijkheid die u kunt gebruiken in Azure Batch: een-op-een-, een-op-veel- en taak-id-bereikafhankelijkheid. Deze drie scenario's kunnen worden gecombineerd tot een vierde scenario: veel-op-veel.

Scenario Voorbeeld Illustratie
Een-op-een taakB is afhankelijk van taakA

taakB wordt niet gepland voor uitvoering totdat taakA is voltooid

Diagram met het afhankelijkheidsscenario voor een-op-een-taak.
Een-op-veel taskC is afhankelijk van zowel taskA als taskB

taskC wordt pas gepland voor uitvoering als taakA en taakB zijn voltooid

Diagram met het afhankelijkheidsscenario voor een-op-veel-taken.
Bereik taak-id taskD is afhankelijk van een bereik van taken

taakD wordt pas gepland voor uitvoering als de taken met id's 1 tot en met 10 zijn voltooid

Diagram met het taakafhankelijkheidsscenario voor taak-id-bereik.

Tip

U kunt veel-op-veel-relaties maken, zoals waarbij taken C, D, E en F elk afhankelijk zijn van de taken A en B. Dit is bijvoorbeeld handig in geparallelliseerde voorverwerkingsscenario's waarbij uw downstreamtaken afhankelijk zijn van de uitvoer van meerdere upstreamtaken.

In de voorbeelden in deze sectie wordt een afhankelijke taak pas uitgevoerd nadat de bovenliggende taken zijn voltooid. Dit gedrag is het standaardgedrag voor een afhankelijke taak. U kunt een afhankelijke taak uitvoeren nadat een bovenliggende taak is mislukt door een afhankelijkheidsactie op te geven om het standaardgedrag te overschrijven.

Een-op-een

In een een-op-een-relatie is een taak afhankelijk van de geslaagde voltooiing van één bovenliggende taak. Als u de afhankelijkheid wilt maken, geeft u één taak-id op voor de statische methode TaskDependencies.OnId wanneer u de eigenschap CloudTask.DependsOn invullen.

// Task 'taskA' doesn't depend on any other tasks
new CloudTask("taskA", "cmd.exe /c echo taskA"),

// Task 'taskB' depends on completion of task 'taskA'
new CloudTask("taskB", "cmd.exe /c echo taskB")
{
    DependsOn = TaskDependencies.OnId("taskA")
},

Een-op-veel

In een een-op-veel-relatie is een taak afhankelijk van de voltooiing van meerdere bovenliggende taken. Als u de afhankelijkheid wilt maken, geeft u een verzameling specifieke taak-id's op voor de statische methode TaskDependencies.OnIds wanneer u de eigenschap CloudTask.DependsOn invullen.

// 'Rain' and 'Sun' don't depend on any other tasks
new CloudTask("Rain", "cmd.exe /c echo Rain"),
new CloudTask("Sun", "cmd.exe /c echo Sun"),

// Task 'Flowers' depends on completion of both 'Rain' and 'Sun'
// before it is run.
new CloudTask("Flowers", "cmd.exe /c echo Flowers")
{
    DependsOn = TaskDependencies.OnIds("Rain", "Sun")
},

Belangrijk

Het maken van de afhankelijke taak mislukt als de gecombineerde lengte van bovenliggende taak-id's groter is dan 64.000 tekens. Als u een groot aantal bovenliggende taken wilt opgeven, kunt u in plaats daarvan een taak-id-bereik gebruiken.

Bereik taak-id

In een afhankelijkheid van een bereik van bovenliggende taken is een taak afhankelijk van de voltooiing van taken waarvan de id's zich binnen een bereik bevinden dat u opgeeft.

Als u de afhankelijkheid wilt maken, geeft u de eerste en laatste taak-id in het bereik op voor de statische methode TaskDependencies.OnIdRange wanneer u de eigenschap CloudTask.DependsOn invullen.

Belangrijk

Wanneer u taak-id-bereiken gebruikt voor uw afhankelijkheden, worden alleen taken met id's die waarden voor gehele getallen vertegenwoordigen geselecteerd door het bereik. Het bereik 1..10 selecteert bijvoorbeeld taken 3 en 7, maar niet 5flamingoes.

Voorloopnullen zijn niet belangrijk bij het evalueren van bereikafhankelijkheden, dus taken met tekenreeks-id's 4, 04 en 004 bevinden zich allemaal binnen het bereik, omdat ze allemaal als taak 4worden behandeld, voldoet de eerste die moet worden voltooid aan de afhankelijkheid.

Om de afhankelijke taak uit te voeren, moet elke taak in het bereik voldoen aan de afhankelijkheid, door deze te voltooien of door te voltooien met een fout die is toegewezen aan een afhankelijkheidsactie die is ingesteld op Voldoen.

// Tasks 1, 2, and 3 don't depend on any other tasks. Because
// we will be using them for a task range dependency, we must
// specify string representations of integers as their ids.
new CloudTask("1", "cmd.exe /c echo 1"),
new CloudTask("2", "cmd.exe /c echo 2"),
new CloudTask("3", "cmd.exe /c echo 3"),

// Task 4 depends on a range of tasks, 1 through 3
new CloudTask("4", "cmd.exe /c echo 4")
{
    // To use a range of tasks, their ids must be integer values.
    // Note that we pass integers as parameters to TaskIdRange,
    // but their ids (above) are string representations of the ids.
    DependsOn = TaskDependencies.OnIdRange(1, 3)
},

Afhankelijkheidsacties

Standaard wordt een afhankelijke taak of set taken alleen uitgevoerd nadat een bovenliggende taak is voltooid. In sommige scenario's wilt u afhankelijke taken uitvoeren, zelfs als de bovenliggende taak mislukt. U kunt het standaardgedrag overschrijven door een afhankelijkheidsactie op te geven die aangeeft of een afhankelijke taak in aanmerking komt voor uitvoering.

Stel dat een afhankelijke taak wacht op gegevens van de voltooiing van de upstream-taak. Als de upstream-taak mislukt, kan de afhankelijke taak mogelijk nog steeds worden uitgevoerd met oudere gegevens. In dit geval kan een afhankelijkheidsactie opgeven dat de afhankelijke taak in aanmerking komt om uit te voeren ondanks het mislukken van de bovenliggende taak.

Een afhankelijkheidsactie is gebaseerd op een afsluitvoorwaarde voor de bovenliggende taak. U kunt een afhankelijkheidsactie opgeven voor een van de volgende afsluitvoorwaarden:

  • Wanneer er een voorverwerkingsfout optreedt.
  • Wanneer er een fout optreedt bij het uploaden van bestanden. Als de taak wordt afgesloten met een afsluitcode die is opgegeven via exitCodes of exitCodeRanges, en er vervolgens een fout optreedt bij het uploaden van bestanden, heeft de actie die is opgegeven door de afsluitcode voorrang.
  • Wanneer de taak wordt afgesloten met een afsluitcode die is gedefinieerd door de eigenschap ExitCodes .
  • Wanneer de taak wordt afgesloten met een afsluitcode die binnen een bereik valt dat is opgegeven door de eigenschap ExitCodeRanges .
  • De standaardcase, als de taak wordt afgesloten met een afsluitcode die niet is gedefinieerd door ExitCodes of ExitCodeRanges, of als de taak wordt afgesloten met een voorverwerkingsfout en de eigenschap PreProcessingError niet is ingesteld, of als de taak mislukt met een bestandsuploadfout en de eigenschap FileUploadError niet is ingesteld.

Voor .NET worden deze voorwaarden gedefinieerd als eigenschappen van de klasse ExitConditions .

Als u een afhankelijkheidsactie wilt opgeven, stelt u de eigenschap ExitOptions.DependencyAction voor de afsluitvoorwaarde in op een van de volgende opties:

  • Voldoen: geeft aan dat afhankelijke taken in aanmerking komen om te worden uitgevoerd als de bovenliggende taak wordt afgesloten met een opgegeven fout.
  • Blokkeren: geeft aan dat afhankelijke taken niet in aanmerking komen om te worden uitgevoerd.

De standaardinstelling voor de eigenschap DependencyAction is Voldoen voor afsluitcode 0 en Blokkeren voor alle andere afsluitvoorwaarden.

Met het volgende codefragment wordt de eigenschap DependencyAction voor een bovenliggende taak ingesteld. Als de bovenliggende taak wordt afgesloten met een voorverwerkingsfout of met de opgegeven foutcodes, wordt de afhankelijke taak geblokkeerd. Als de bovenliggende taak wordt afgesloten met een andere fout dan nul, komt de afhankelijke taak in aanmerking voor uitvoering.

// Task A is the parent task.
new CloudTask("A", "cmd.exe /c echo A")
{
    // Specify exit conditions for task A and their dependency actions.
    ExitConditions = new ExitConditions
    {
        // If task A exits with a pre-processing error, block any downstream tasks (in this example, task B).
        PreProcessingError = new ExitOptions
        {
            DependencyAction = DependencyAction.Block
        },
        // If task A exits with the specified error codes, block any downstream tasks (in this example, task B).
        ExitCodes = new List<ExitCodeMapping>
        {
            new ExitCodeMapping(10, new ExitOptions() { DependencyAction = DependencyAction.Block }),
            new ExitCodeMapping(20, new ExitOptions() { DependencyAction = DependencyAction.Block })
        },
        // If task A succeeds or fails with any other error, any downstream tasks become eligible to run 
        // (in this example, task B).
        Default = new ExitOptions
        {
            DependencyAction = DependencyAction.Satisfy
        }
    }
},
// Task B depends on task A. Whether it becomes eligible to run depends on how task A exits.
new CloudTask("B", "cmd.exe /c echo B")
{
    DependsOn = TaskDependencies.OnId("A")
},

Codevoorbeeld

In het voorbeeldproject TaskDependencies op GitHub ziet u het volgende:

  • Taakafhankelijkheid van een taak inschakelen.
  • Taken maken die afhankelijk zijn van andere taken.
  • Deze taken uitvoeren in een pool met rekenknooppunten.

Volgende stappen