Udostępnij za pośrednictwem


Tworzenie zależności zadań w celu uruchamiania zadań, które zależą od innych zadań

Zależności zadań podrzędnych usługi Batch umożliwiają tworzenie zadań zaplanowanych do wykonania w węzłach obliczeniowych po zakończeniu co najmniej jednego zadania nadrzędnego. Można na przykład utworzyć zadanie, które renderuje każdą ramkę filmu 3D z oddzielnymi zadaniami równoległymi. Ostatnie zadanie scala renderowane ramki do kompletnego filmu dopiero po pomyślnym renderowaniu wszystkich ramek. Innymi słowy, ostateczne zadanie jest zależne od poprzednich zadań nadrzędnych.

Niektóre scenariusze, w których zależności zadań są przydatne, obejmują:

  • Obciążenia w stylu MapReduce w chmurze.
  • Zadania, których zadania przetwarzania danych można wyrazić jako skierowany graf acykliczny (DAG).
  • Procesy przed renderowaniem i po renderowaniu, w których każde zadanie musi zostać ukończone przed rozpoczęciem następnego zadania.
  • Każde inne zadanie, w którym podrzędne zadania zależą od danych wyjściowych zadań nadrzędnych.

Domyślnie zadania zależne są zaplanowane do wykonania dopiero po pomyślnym zakończeniu zadania nadrzędnego. Opcjonalnie można określić akcję zależności, aby zastąpić domyślne zachowanie i uruchomić zadanie zależne, nawet jeśli zadanie nadrzędne zakończy się niepowodzeniem.

W tym artykule omówiono sposób konfigurowania zależności zadań przy użyciu biblioteki platformy .NET usługi Batch. Najpierw pokazano, jak włączyć zależność zadania od zadań, a następnie pokazać, jak skonfigurować zadanie z zależnościami. Opisujemy również sposób określania akcji zależności w celu uruchamiania zadań zależnych w przypadku niepowodzenia elementu nadrzędnego. Na koniec omówimy scenariusze zależności obsługiwane przez usługę Batch.

Włączanie zależności zadań

Aby używać zależności zadań w aplikacji usługi Batch, należy najpierw skonfigurować zadanie do korzystania z zależności zadań. Na platformie .NET usługi Batch włącz ją w ramach zadania CloudJob, ustawiając właściwość UsesTaskDependencies na :true

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

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

W poprzednim fragmencie kodu "batchClient" jest wystąpieniem klasy BatchClient .

Tworzenie zadań zależnych

Aby utworzyć zadanie, które zależy od ukończenia co najmniej jednego zadania nadrzędnego, można określić, że zadanie "zależy od" innych zadań. Na platformie .NET usługi Batch skonfiguruj właściwość CloudTask.DependsOn przy użyciu wystąpienia klasy 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")
},

Ten fragment kodu tworzy zależne zadanie o identyfikatorze zadania "Kwiaty". Zadanie "Kwiaty" zależy od zadań "Deszcz" i "Słońce". Zadanie "Kwiaty" zostanie zaplanowane do uruchomienia w węźle obliczeniowym dopiero po pomyślnym zakończeniu zadań "Deszcz" i "Sun".

Uwaga

Domyślnie zadanie jest uznawane za ukończone pomyślnie, gdy znajduje się w stanie ukończonym, a jego kod zakończenia to 0. Na platformie .NET usługi Batch oznacza to, że wartość właściwości CloudTask.State to Completed , a wartość właściwości TaskExecutionInformation.ExitCode w usłudze CloudTask to 0. Aby dowiedzieć się, jak to zmienić, zobacz sekcję Akcje zależności.

Scenariusze zależności

Istnieją trzy podstawowe scenariusze zależności zadań, których można użyć w usłudze Azure Batch: zależność jeden do jednego, jeden do wielu i zakres identyfikatorów zadań. Te trzy scenariusze można połączyć, aby zapewnić czwarty scenariusz: wiele do wielu.

Scenariusz Przykład Ilustracja
Jeden do jednego ZadanieB zależy od zadaniaB zadaniaB

nie zostanie zaplanowane do wykonania, dopóki zadanieA nie zostanie ukończone pomyślnie

Diagram przedstawiający scenariusz zależności zadania jeden do jednego.
Jeden do wielu ZadanieC zależy zarówno od zadaniaA, jak i taskB

podrzędnegoC nie zostanie zaplanowane do wykonania, dopóki zadanieA i zadanieB nie zostaną ukończone pomyślnie

Diagram przedstawiający scenariusz zależności zadania jeden do wielu.
Zakres identyfikatorów zadań taskD zależy od zakresu zadań

podrzędnych, których zadanie podrzędne nie zostanie zaplanowane do wykonania, dopóki zadania z identyfikatorami od 1 do 10 nie zostaną ukończone pomyślnie

Diagram przedstawiający scenariusz zależności zakresu zadań zakresu zadań.

Napiwek

Można tworzyć relacje wiele-do-wielu , takie jak miejsca, w których zadania C, D, E i F zależą od zadań A i B. Jest to przydatne, na przykład w scenariuszach równoległego przetwarzania wstępnego, w których podrzędne zadania zależą od danych wyjściowych wielu zadań nadrzędnych.

W przykładach w tej sekcji zależne zadanie jest uruchamiane dopiero po pomyślnym zakończeniu zadań nadrzędnych. To zachowanie jest zachowaniem domyślnym dla zadania zależnego. Zadanie zależne można uruchomić po niepomyślnym wykonaniu zadania nadrzędnego, określając akcję zależności, aby zastąpić domyślne zachowanie.

Jeden do jednego

W relacji jeden do jednego zadanie zależy od pomyślnego ukończenia jednego zadania nadrzędnego. Aby utworzyć zależność, podaj pojedynczy identyfikator zadania dla metody statycznej TaskDependencies.OnId podczas wypełniania właściwości CloudTask.DependsOn.

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

Jeden-do-wielu

W relacji jeden do wielu zadanie zależy od ukończenia wielu zadań nadrzędnych. Aby utworzyć zależność, po wypełnieniu właściwości CloudTask.DependsOn podaj kolekcję określonych identyfikatorów zadań do metody statycznej 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")
},

Ważne

Tworzenie zadania zależnego zakończy się niepowodzeniem, jeśli łączna długość identyfikatorów zadań nadrzędnych jest większa niż 64000 znaków. Aby określić dużą liczbę zadań nadrzędnych, rozważ użycie zakresu identyfikatorów zadań.

Zakres identyfikatorów zadań

W zależności od zakresu zadań nadrzędnych zadanie zależy od ukończenia zadań, których identyfikatory znajdują się w określonym zakresie.

Aby utworzyć zależność, podaj identyfikatory pierwszego i ostatniego zadania w zakresie do metody statycznej TaskDependencies.OnIdRange podczas wypełniania właściwości CloudTask.DependsOn .

Ważne

W przypadku używania zakresów identyfikatorów zadań dla zależności zakresy będą wybierane tylko zadania z identyfikatorami reprezentującymi wartości całkowite. Na przykład zakres 1..10 wybierze zadania 3 i 7, ale nie 5flamingoes.

Zera wiodące nie są istotne podczas oceniania zależności zakresu, więc zadania z identyfikatorami ciągów 404 i 004 wszystkie będą znajdować się w zakresie, ponieważ wszystkie będą traktowane jako zadanie 4, pierwszy do ukończenia spełni zależność.

Aby zadanie zależne było uruchamiane, każde zadanie w zakresie musi spełniać zależność, kończąc je pomyślnie lub kończąc z błędem zamapowanym na akcję zależności ustawioną na Wartość Spełnij.

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

Akcje zależności

Domyślnie zależne zadanie lub zestaw zadań są uruchamiane tylko po pomyślnym zakończeniu zadania nadrzędnego. W niektórych scenariuszach możesz chcieć uruchamiać zadania zależne, nawet jeśli zadanie nadrzędne zakończy się niepowodzeniem. Domyślne zachowanie można zastąpić, określając akcję zależności, która wskazuje, czy zadanie zależne kwalifikuje się do uruchomienia.

Załóżmy na przykład, że zależne zadanie oczekuje na dane od ukończenia zadania nadrzędnego. Jeśli zadanie nadrzędne zakończy się niepowodzeniem, zależne zadanie może nadal być w stanie uruchomić przy użyciu starszych danych. W takim przypadku akcja zależności może określać, że zależne zadanie kwalifikuje się do uruchomienia pomimo niepowodzenia zadania nadrzędnego.

Akcja zależności jest oparta na warunku zakończenia zadania nadrzędnego. Możesz określić akcję zależności dla dowolnego z następujących warunków zakończenia:

  • W przypadku wystąpienia błędu przetwarzania wstępnego.
  • Gdy wystąpi błąd przekazywania pliku. Jeśli zadanie kończy działanie z kodem zakończenia określonym za pośrednictwem exitCodes lub exitCodeRanges, a następnie napotka błąd przekazywania pliku, akcja określona przez kod zakończenia ma pierwszeństwo.
  • Gdy zadanie zakończy działanie z kodem zakończenia zdefiniowanym przez właściwość ExitCodes .
  • Gdy zadanie kończy działanie z kodem zakończenia należącym do zakresu określonego przez właściwość ExitCodeRanges .
  • Domyślny przypadek, jeśli zadanie kończy działanie z kodem zakończenia, który nie jest zdefiniowany przez ExitCodes lub ExitCodeRanges, lub jeśli zadanie kończy się z błędem przetwarzania wstępnego i właściwość PreProcessingError nie jest ustawiona lub jeśli zadanie zakończy się niepowodzeniem z błędem przekazywania pliku i właściwość FileUploadError nie jest ustawiona.

W przypadku platformy .NET te warunki są definiowane jako właściwości klasy ExitConditions .

Aby określić akcję zależności, ustaw właściwość ExitOptions.DependencyAction dla warunku zakończenia na jedną z następujących wartości:

  • Spełnianie: wskazuje, że zadania zależne kwalifikują się do uruchomienia, jeśli zadanie nadrzędne zakończy działanie z określonym błędem.
  • Blokuj: wskazuje, że zadania zależne nie kwalifikują się do uruchomienia.

Ustawieniem domyślnym właściwości DependencyAction jest Spełnianie dla kodu zakończenia 0 i Blokuj dla wszystkich innych warunków zakończenia.

Poniższy fragment kodu ustawia właściwość DependencyAction dla zadania nadrzędnego. Jeśli zadanie nadrzędne kończy działanie z powodu błędu przetwarzania wstępnego lub z określonymi kodami błędów, zadanie zależne jest blokowane. Jeśli zadanie nadrzędne zakończy działanie z innym błędem innym niż zero, zależne zadanie kwalifikuje się do uruchomienia.

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

Przykład kodu

Przykładowy projekt TaskDependencies w usłudze GitHub pokazuje:

  • Jak włączyć zależność zadania od zadania.
  • Jak tworzyć zadania zależne od innych zadań.
  • Jak wykonywać te zadania w puli węzłów obliczeniowych.

Następne kroki