Tworzenie zależności zadań w celu uruchamiania zadań, które zależą od innych zadań
W przypadku zależności zadań usługi Batch można tworzyć zadania zaplanowane 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. Zadanie końcowe scala renderowane ramki do kompletnego filmu dopiero po pomyślnym renderowaniu wszystkich ramek. Innymi słowy, końcowe zadanie jest zależne od poprzednich zadań nadrzędnych.
Niektóre scenariusze, w których przydatne są zależności zadań:
- 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 podrzędnych podrzędnych zadań podrzę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 .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 do uruchamiania zadań zależnych, jeśli element nadrzędny zakończy się niepowodzeniem. 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 zależne 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 z wystąpieniem 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 ukoń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 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 | Ilustracji |
---|---|---|
Jeden do jednego | taskB zależy od zadaniaA taskB nie będzie zaplanowane do wykonania, dopóki zadanieA nie zakończy się pomyślnie | |
Jeden do wielu | taskC zależy zarówno od zadaniaA, jak i taskBtaskC nie będzie zaplanowane do wykonania, dopóki zadanieA i zadanieB nie zostaną ukończone pomyślnie | |
Zakres identyfikatorów zadań | taskD zależy od zakresu zadań podrzędnychD nie zostaną zaplanowane do wykonania, dopóki zadania z identyfikatorami od 1 do 10 zostały ukończone pomyślnie |
Porada
Można tworzyć relacje wiele-do-wielu , takie jak zadania C, D, E i F, które 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 nadrzędnych zadań.
W przykładach w tej sekcji zależne zadanie jest uruchamiane tylko po pomyślnym zakończeniu zadań nadrzędnych. To zachowanie jest domyślnym zachowaniem zadania zależnego. Zadanie zależne można uruchomić po niepomyślnym zadaniu nadrzędnym, 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 do 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ść, podaj kolekcję określonych identyfikatorów zadań do metody statycznej TaskDependencies.OnIds podczas wypełniania właściwości CloudTask.DependsOn .
// '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 pierwsze i ostatnie identyfikatory zadań 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 tylko zadania z identyfikatorami reprezentującymi wartości całkowite zostaną wybrane przez zakres. 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 4
04
004
i 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 pomyślnie lub kończąc z niepowodzeniem mapowanym 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ń jest uruchamiany tylko po pomyślnym zakończeniu zadania nadrzędnego. W niektórych scenariuszach możesz chcieć uruchamiać zadania zależne nawet wtedy, gdy 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 zależne zadanie 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ślić, ż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:
- Gdy wystąpi błąd przetwarzania wstępnego.
- Po wystąpieniu błędu 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.
- Po zakończeniu zadania z kodem zakończenia zdefiniowanym przez właściwość ExitCodes .
- Gdy zadanie kończy działanie z kodem zakończenia, który mieści się w zakresie określonym przez właściwość ExitCodeRanges .
- Domyślny przypadek, jeśli zadanie kończy działanie z kodem zakończenia niezdefiniowany przez exitCodes lub ExitCodeRanges, lub jeśli zadanie kończy działanie 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 wymagań: wskazuje, że zadania zależne kwalifikują się do uruchomienia, jeśli zadanie nadrzędne koń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 się z błędem przetwarzania wstępnego lub z określonymi kodami błędów, zadanie zależne zostanie zablokowane. Jeśli zadanie nadrzędne koń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 przedstawia:
- 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
- Dowiedz się więcej o funkcji pakietów aplikacji usługi Batch, która zapewnia łatwy sposób wdrażania i wersji aplikacji wykonywanych przez zadania w węzłach obliczeniowych.
- Dowiedz się więcej o sprawdzaniu błędów pod kątem zadań i zadań.