Vytvoření závislostí úkolů pro spouštění úloh, které závisí na jiných úkolech

Pomocí závislostí úkolů služby Batch vytvoříte úkoly, které jsou naplánované pro spuštění na výpočetních uzlech po dokončení jednoho nebo více nadřazených úkolů. Můžete například vytvořit úlohu, která vykresluje každý snímek 3D filmu se samostatnými paralelními úkoly. Konečný úkol sloučí vykreslené snímky do kompletního videa až po úspěšném vykreslení všech snímků. Jinými slovy, konečný úkol závisí na předchozích nadřazených úkolech.

Mezi scénáře, ve kterých jsou závislosti úkolů užitečné, patří:

  • Úlohy ve stylu MapReduce v cloudu.
  • Úlohy, jejichž úlohy zpracování dat lze vyjádřit jako orientovaný acyklický graf (DAG).
  • Procesy před vykreslováním a po vykreslení, kdy každý úkol musí být dokončen před zahájením dalšího úkolu.
  • Jakákoli jiná úloha, ve které podřízené úkoly závisí na výstupu nadřazených úkolů.

Ve výchozím nastavení jsou závislé úlohy naplánovány pro provádění až po úspěšném dokončení nadřazené úlohy. Volitelně můžete zadat akci závislosti , která přepíše výchozí chování a spustí závislou úlohu i v případě, že nadřazená úloha selže.

V tomto článku si probereme, jak nakonfigurovat závislosti úloh pomocí knihovny Batch .NET . Nejprve vám ukážeme, jak povolit závislost na úlohách , a pak předvedeme, jak nakonfigurovat úkol se závislostmi. Popisujeme také, jak určit akci závislosti pro spuštění závislých úloh v případě selhání nadřazeného objektu. Nakonec probereme scénáře závislostí , které služba Batch podporuje.

Povolení závislostí úkolů

Pokud chcete v aplikaci Batch používat závislosti úloh, musíte nejprve nakonfigurovat úlohu tak, aby používala závislosti úkolů. Ve službě Batch .NET ji povolte ve své cloudové službě nastavením jeho vlastnosti UsesTaskDependencies na truehodnotu :

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

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

V předchozím fragmentu kódu je "batchClient" instance třídy BatchClient .

Vytváření závislých úkolů

Pokud chcete vytvořit úkol, který závisí na dokončení jednoho nebo více nadřazených úkolů, můžete určit, že úkol "závisí" na ostatních úkolech. Ve službě Batch .NET nakonfigurujte vlastnost CloudTask.DependsOn s instancí třídy 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")
},

Tento fragment kódu vytvoří závislý úkol s ID úkolu "Květiny". Úkol "Květiny" závisí na úkolech "Déšť" a "Slunce". Úkol "Květiny" bude naplánován tak, aby běžel na výpočetním uzlu až po úspěšném dokončení úkolů "Déšť" a "Slunce".

Poznámka

Ve výchozím nastavení se úkol považuje za úspěšně dokončený, když je v dokončeném stavu a jeho ukončovací kód je 0. Ve službě Batch .NET to znamená, že hodnota vlastnosti CloudTask.State je Completed a hodnota vlastnosti TaskExecutionInformation.ExitCode pro CloudTask je 0. Informace o tom, jak to změnit, najdete v části Akce závislostí .

Scénáře závislostí

Existují tři základní scénáře závislostí úkolů, které můžete použít v Azure Batch: 1:1, 1:N a závislost rozsahu ID úkolů. Tyto tři scénáře je možné zkombinovat a poskytnout tak čtvrtý scénář: M:N.

Scenario Příklad Obrázek
Relace jednoho k jednomu jinému taskB závisí na úkolu:

ÚkolB nebude naplánovaný ke spuštění, dokud se úlohaA úspěšně nedokončí.

Diagram znázorňující scénář závislosti úloh 1:1
1:N taskC závisí na úkolu: Úkol A i úkolB

se neplánuje ke spuštění, dokud se úlohaA i taskB úspěšně nedokončí.

Diagram znázorňující scénář závislosti úloh 1:N
Rozsah ID úkolu taskD závisí na řadě úkolů

: ÚkolD nebude naplánovaný pro provádění, dokud se úlohy s ID 110 úspěšně nedokončily.

Diagram znázorňující scénář závislostí úkolů rozsahu ID úkolu

Tip

Můžete vytvořit relace M:N , například kde úkoly C, D, E a F závisejí na úkolech A a B. To je užitečné například ve scénářích paralelizovaného předzpracování, kde vaše podřízené úkoly závisí na výstupu několika upstreamových úloh.

V příkladech v této části se závislý úkol spustí až po úspěšném dokončení nadřazených úkolů. Toto chování je výchozí chování pro závislý úkol. Závislý úkol můžete spustit po selhání nadřazeného úkolu zadáním akce závislosti , která přepíše výchozí chování.

Relace jednoho k jednomu jinému

V relaci 1:1 závisí úkol na úspěšném dokončení jednoho nadřazeného úkolu. Pokud chcete vytvořit závislost, při naplnění vlastnosti CloudTask.DependsOn zadejte do statické metody TaskDependencies.OnId ID jednoho úkolu.

// 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")
},

1:N

V relaci 1:N závisí úkol na dokončení více nadřazených úkolů. Pokud chcete vytvořit závislost, při naplnění vlastnosti CloudTask.DependsOn poskytněte kolekci ID konkrétních úloh do statické metody TaskDependencies.OnIds.

// '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")
},

Důležité

Vytvoření závislého úkolu se nezdaří, pokud je celková délka ID nadřazených úkolů větší než 64000 znaků. Pokud chcete zadat velký počet nadřazených úkolů, zvažte místo toho použití rozsahu ID úkolu.

Rozsah ID úkolu

V závislosti na rozsahu nadřazených úkolů závisí úkol na dokončení úkolů, jejichž ID leží v zadaném rozsahu.

Chcete-li vytvořit závislost, při naplnění vlastnosti CloudTask.DependsOn zadejte ID prvního a posledního úkolu v oblasti do statické metody TaskDependencies.OnIdRange.

Důležité

Pokud pro své závislosti použijete rozsahy ID úkolů, budou vybrány pouze úkoly s ID představujícími celočíselné hodnoty. Rozsah 1..10 například vybere úkoly 3 a 7, ale ne 5flamingoes.

Počáteční nuly nejsou při vyhodnocování závislostí rozsahu významné, takže úkoly s identifikátory 404 řetězců a 004 budou všechny v rozsahu, protože se všechny budou považovat za úkol4, první dokončení bude závislosti vyhovovat.

Aby se závislý úkol spustil, musí každý úkol v rozsahu splňovat závislost, a to buď tak, že se úspěšně dokončí, nebo dokončením s chybou, která je namapována na akci závislosti nastavenou na Uspokojit.

// 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)
},

Akce závislostí

Ve výchozím nastavení se závislý úkol nebo sada úkolů spustí až po úspěšném dokončení nadřazeného úkolu. V některých scénářích můžete chtít spouštět závislé úlohy i v případě, že nadřazená úloha selže. Výchozí chování můžete přepsat zadáním akce závislosti , která indikuje, jestli je závislý úkol způsobilý ke spuštění.

Předpokládejme například, že závislý úkol čeká na data z dokončení nadřazeného úkolu. Pokud nadřazený úkol selže, závislý úkol může být stále schopen spustit pomocí starších dat. V tomto případě může akce závislosti určit, že závislý úkol je způsobilý ke spuštění navzdory selhání nadřazeného úkolu.

Akce závislosti je založena na výstupní podmínce pro nadřazený úkol. Akci závislosti můžete zadat pro některou z následujících podmínek ukončení:

  • Když dojde k chybě předběžného zpracování.
  • Když dojde k chybě při nahrávání souboru. Pokud se úloha ukončí s ukončovacím kódem zadaným prostřednictvím exitCodes nebo exitCodeRanges a pak dojde k chybě nahrávání souboru, bude mít přednost akce určená ukončovacím kódem.
  • Při ukončení úlohy s ukončovacím kódem definovaným vlastností ExitCodes .
  • Při ukončení úkolu s ukončovací kód, který spadá do rozsahu určeného ExitCodeRanges vlastnost.
  • Výchozí případ, pokud se úloha ukončí s ukončovacím kódem, který není definován v exitcodes nebo ExitCodeRanges, nebo pokud se úkol ukončí s chybou předběžného zpracování a není nastavena vlastnost PreProcessingError , nebo pokud úloha selže s chybou nahrávání souboru a fileUploadError vlastnost není nastavena.

Pro .NET jsou tyto podmínky definovány jako vlastnosti třídy ExitConditions .

Pokud chcete zadat akci závislosti, nastavte vlastnost ExitOptions.DependencyAction pro výstupní podmínku na jednu z následujících možností:

  • Uspokojit: Označuje, že závislé úkoly jsou způsobilé ke spuštění, pokud se nadřazený úkol ukončí se zadanou chybou.
  • Blokovat: Označuje, že závislé úkoly nejsou způsobilé ke spuštění.

Výchozí nastavení vlastnosti DependencyAction je Satisfy pro ukončovací kód 0 a Blokovat pro všechny ostatní podmínky ukončení.

Následující fragment kódu nastaví vlastnost DependencyAction pro nadřazenou úlohu. Pokud se nadřazený úkol ukončí s chybou předběžného zpracování nebo se zadanými kódy chyb, závislý úkol se zablokuje. Pokud se nadřazený úkol ukončí s jakoukoli jinou nenulovou chybou, je závislý úkol způsobilý ke spuštění.

// 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")
},

Ukázka kódu

Ukázkový projekt TaskDependencies na GitHubu ukazuje:

  • Postup povolení závislosti úloh na úloze
  • Jak vytvořit úkoly, které jsou závislé na jiných úkolech.
  • Jak provádět tyto úlohy ve fondu výpočetních uzlů.

Další kroky