Tutorial: Ausführen einer parallelen Workload mit Azure Batch über die .NET-API

Mithilfe von Azure Batch können Sie umfangreiche auf Parallelverarbeitung ausgelegte HPC-Batchaufträge (High Performance Computing) effizient in Azure ausführen. In diesem Tutorial wird Schritt für Schritt ein C#-Beispiel für die Ausführung einer parallelen Workload per Batch beschrieben. Sie erfahren, wie Sie einen gängigen Batch-Anwendungsworkflow durchführen und programmgesteuert mit Batch- und Storage-Ressourcen interagieren.

  • Hinzufügen eines Anwendungspakets zu Ihrem Batch-Konto.
  • Authentifizieren mit Batch- und Storage-Konten.
  • Hochladen von Eingabedateien in Storage.
  • Erstellen eines Pools mit Computeknoten für die Ausführung einer Anwendung.
  • Erstellen eines Auftrags und von Aufgaben zum Verarbeiten von Eingabedateien.
  • Überwachen der Aufgabenausführung
  • Abrufen von Ausgabedateien.

In diesem Tutorial konvertieren Sie MP4-Mediendateien parallel in das MP3-Format, indem Sie das Open-Source-Tool ffmpeg verwenden.

Wenn Sie kein Azure-Abonnement haben, erstellen Sie ein kostenloses Azure-Konto, bevor Sie beginnen.

Voraussetzungen

  • Visual Studio 2017 oder höher bzw. .NET Core SDK für Linux, macOS oder Windows.

  • Ein Batch-Konto und ein verknüpftes Azure Storage-Konto. Informationen zur Erstellung dieser Konten finden Sie in den Batch-Schnellstartanleitungen zum Azure-Portal oder zur Azure CLI.

  • Laden Sie die geeignete Version von ffmpeg für Ihren Einsatzfall auf Ihren lokalen Computer herunter. In diesem Tutorial und der zugehörigen Beispiel-App wird die komplette Windows 64-Bit-Buildversion von ffmpeg 4.3.1 verwendet. Für dieses Tutorial benötigen Sie nur die ZIP-Datei. Es ist nicht erforderlich, die Datei zu entzippen oder sie lokal zu installieren.

Anmelden bei Azure

Melden Sie sich beim Azure-Portal an.

Hinzufügen eines Anwendungspakets

Verwenden Sie das Azure-Portal, um ffmpeg Ihrem Batch-Konto als Anwendungspaket hinzuzufügen. Mit Anwendungspaketen können Sie Aufgabenanwendungen und die dazugehörige Bereitstellung auf den Computeknoten in Ihrem Pool verwalten.

  1. Klicken Sie im Azure-Portal auf Weitere Dienste>Batch-Konten, und wählen Sie dann den Namen Ihres Batch-Kontos aus.

  2. Klicken Sie auf Anwendungen>Hinzufügen.

    Screenshot of the Applications section of the batch account.

  3. Geben Sie ffmpeg in das Feld Anwendungs-ID und die Paketversion 4.3.1 in das Feld Version ein. Wählen Sie die Datei „ffmpeg.zip“ aus, die Sie heruntergeladen haben, und klicken Sie auf Senden. Das ffmpeg-Anwendungspaket wird Ihrem Batch-Konto hinzugefügt.

    Screenshot of the ID and version fields in the Add application section.

Abrufen der Kontoanmeldeinformationen

In diesem Beispiel müssen Sie Anmeldeinformationen für Ihr Batch- und Ihr Storage-Konto angeben. Die erforderlichen Anmeldeinformationen können Sie ganz einfach über das Azure-Portal abrufen. (Sie können aber auch die Azure-APIs oder Befehlszeilentools verwenden, um die Anmeldeinformationen abzurufen.)

  1. Wählen Sie Alle Dienste>Batch-Konten und anschließend den Namen Ihres Batch-Kontos aus.

  2. Wählen Sie zum Anzeigen der Batch-Anmeldeinformationen Schlüssel aus. Kopieren Sie die Werte für Batch-Konto, URL und Primärer Zugriffsschlüssel in einen Texteditor.

  3. Wählen Sie zum Anzeigen des Namens und der Schlüssel für das Storage-Konto auf Speicherkonto aus. Kopieren Sie die Werte für Speicherkontoname und Schlüssel1 in einen Texteditor.

Herunterladen und Ausführen der Beispiel-App

Herunterladen der Beispiel-App

Laden Sie die Beispiel-App von GitHub herunter, oder klonen Sie sie. Verwenden Sie den folgenden Befehl, um das Beispiel-App-Repository mit einem Git-Client zu klonen:

git clone https://github.com/Azure-Samples/batch-dotnet-ffmpeg-tutorial.git

Navigieren Sie zu dem Verzeichnis, in dem die Visual Studio-Projektmappendatei BatchDotNetFfmpegTutorial.sln enthalten ist.

Öffnen Sie die Projektmappendatei in Visual Studio, und aktualisieren Sie die Zeichenfolgen mit den Anmeldeinformationen in Program.cs mit den Werten für Ihre Konten. Beispiel:

// Batch account credentials
private const string BatchAccountName = "yourbatchaccount";
private const string BatchAccountKey  = "xxxxxxxxxxxxxxxxE+yXrRvJAqT9BlXwwo1CwF+SwAYOxxxxxxxxxxxxxxxx43pXi/gdiATkvbpLRl3x14pcEQ==";
private const string BatchAccountUrl  = "https://yourbatchaccount.yourbatchregion.batch.azure.com";

// Storage account credentials
private const string StorageAccountName = "yourstorageaccount";
private const string StorageAccountKey  = "xxxxxxxxxxxxxxxxy4/xxxxxxxxxxxxxxxxfwpbIC5aAWA8wDu+AFXZB827Mt9lybZB1nUcQbQiUrkPtilK5BQ==";

Hinweis

Zur Vereinfachung des Beispiels sind die Anmeldeinformationen für das Batch- und Storage-Konto in Klartext angegeben. Für die Praxis empfehlen wir Ihnen, den Zugriff auf die Anmeldeinformationen zu beschränken und im Code darauf zu verweisen, indem Sie Umgebungsvariablen oder eine Konfigurationsdatei verwenden. Beispiele hierfür finden Sie im Repository mit den Codebeispielen für Azure Batch.

Stellen Sie außerdem sicher, dass der Verweis auf das ffmpeg-Anwendungspaket in der Lösung mit dem Bezeichner und der Version des ffmpeg-Pakets übereinstimmt, das Sie in Ihr Batch-Konto hochgeladen haben. Beispiel: ffmpeg und 4.3.1.

const string appPackageId = "ffmpeg";
const string appPackageVersion = "4.3.1";

Erstellen und Ausführen des Beispielprojekts

Verwenden Sie für das Erstellen und Ausführen der Anwendung Visual Studio oder die Befehlszeile mit den Befehlen dotnet build und dotnet run. Sehen Sie sich nach dem Ausführen der Anwendung den Code an, um zu erfahren, welche Aufgabe die einzelnen Teile der Anwendung jeweils haben. In Visual Studio:

  1. Klicken Sie mit der rechten Maustaste in den Projektmappen-Explorer, und wählen Sie Projektmappe erstellen aus.

  2. Bestätigen Sie die Wiederherstellung von NuGet-Paketen, wenn Sie hierzu aufgefordert werden. Stellen Sie beim Herunterladen von fehlenden Paketen sicher, dass der NuGet-Paket-Manager installiert ist.

  3. Führen Sie die Lösung aus. Beim Ausführen der Beispielanwendung sieht die Konsolenausgabe in etwa wie folgt aus: Bei der Ausführung kommt es bei Monitoring all tasks for 'Completed' state, timeout in 00:30:00... zu einer Pause, während die Computeknoten des Pools gestartet werden.

Sample start: 11/19/2018 3:20:21 PM

Container [input] created.
Container [output] created.
Uploading file LowPriVMs-1.mp4 to container [input]...
Uploading file LowPriVMs-2.mp4 to container [input]...
Uploading file LowPriVMs-3.mp4 to container [input]...
Uploading file LowPriVMs-4.mp4 to container [input]...
Uploading file LowPriVMs-5.mp4 to container [input]...
Creating pool [WinFFmpegPool]...
Creating job [WinFFmpegJob]...
Adding 5 tasks to job [WinFFmpegJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
Success! All tasks completed successfully within the specified timeout period.
Deleting container [input]...

Sample end: 11/19/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742

Navigieren Sie im Azure-Portal zu Ihrem Batch-Konto, um den Pool, die Computeknoten, den Auftrag und die Aufgaben zu überwachen. Klicken Sie beispielsweise auf Pools>WinFFmpegPool, um ein Wärmebild mit den Computeknoten Ihres Pools anzuzeigen.

Bei der Ausführung von Aufgaben sieht das Wärmebild in etwa wie folgt aus:

Screenshot of the pool heat map in the Azure portal.

Die normale Ausführungsdauer beträgt ca. zehn Minuten, wenn die Anwendung in der Standardkonfiguration ausgeführt wird. Die meiste Zeit wird für die Poolerstellung benötigt.

Abrufen von Ausgabedateien

Sie können das Azure-Portal verwenden, um die ausgegebenen MP3-Dateien herunterzuladen, die durch die ffmpeg-Aufgaben generiert werden.

  1. Klicken Sie auf Alle Dienste>Speicherkonten und anschließend auf den Namen Ihres Speicherkontos.
  2. Klicken Sie auf Blobs>Ausgabe.
  3. Klicken Sie mit der rechten Maustaste auf eine der ausgegebenen MP3-Dateien, und klicken Sie anschließend auf Herunterladen. Folgen Sie den Anweisungen in Ihrem Browser, um die Datei zu öffnen oder zu speichern.

Download output file

Die Dateien können auch programmgesteuert aus den Computeknoten oder aus dem Speichercontainer heruntergeladen werden. Dies wird in diesem Beispiel allerdings nicht gezeigt.

Überprüfen des Codes

In den folgenden Abschnitten ist die Beispielanwendung in die Schritte unterteilt, die ausgeführt werden, um eine Workload im Batch-Dienst zu verarbeiten. Verwenden Sie beim Lesen des restlichen Teils dieses Artikels die Datei Program.cs der Projektmappe, da nicht jede Codezeile im Beispiel beschrieben wird.

Authentifizieren des Blobs und der Batch-Clients

Zum Interagieren mit dem verknüpften Speicherkonto verwendet die App die Azure Storage-Clientbibliothek für .NET. Sie erstellt mit CloudStorageAccount einen Verweis auf das Konto, und es wird die Authentifizierung mit gemeinsam verwendetem Schlüssel genutzt. Anschließend wird ein CloudBlobClient-Element erstellt.

// Construct the Storage account connection string
string storageConnectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                StorageAccountName, StorageAccountKey);

// Retrieve the storage account
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);

CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

Die App erstellt ein BatchClient-Objekt zum Erstellen und Verwalten von Pools, Aufträgen und Aufgaben im Batch-Dienst. Für den Batch-Client im Beispiel wird die Authentifizierung mit gemeinsam verwendetem Schlüssel genutzt. Batch unterstützt auch die Authentifizierung per Microsoft Entra ID, um einzelne Benutzer oder eine unbeaufsichtigte Anwendung zu authentifizieren.

BatchSharedKeyCredentials sharedKeyCredentials = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

using (BatchClient batchClient = BatchClient.Open(sharedKeyCredentials))
...

Hochladen von Eingabedateien

Die App übergibt das blobClient-Objekt an die CreateContainerIfNotExistAsync-Methode, um einen Speichercontainer für die Eingabedateien (MP4-Format) und einen Container für die Aufgabenausgabe zu erstellen.

CreateContainerIfNotExistAsync(blobClient, inputContainerName);
CreateContainerIfNotExistAsync(blobClient, outputContainerName);

Anschließend werden Dateien aus dem lokalen Ordner InputFiles in den Eingabecontainer hochgeladen. Die Dateien im Speicher werden als Batch-ResourceFile-Objekte definiert, die von Batch später auf Computeknoten heruntergeladen werden können.

Am Upload der Dateien sind in Program.cs zwei Methoden beteiligt:

  • UploadFilesToContainerAsync: Gibt eine Sammlung mit ResourceFile-Objekten zurück und ruft intern UploadResourceFileToContainerAsync auf, um die einzelnen Dateien hochzuladen, die im Parameter inputFilePaths übergeben werden.
  • UploadResourceFileToContainerAsync: Lädt jede Datei als Blob in den Eingabecontainer hoch. Nach dem Hochladen der Datei wird eine Shared Access Signature (SAS) für das Blob abgerufen, und es wird ein ResourceFile-Objekt zurückgegeben, um das Blob darzustellen.
string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");

List<string> inputFilePaths = new List<string>(Directory.GetFileSystemEntries(inputPath, "*.mp4",
    SearchOption.TopDirectoryOnly));

List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(
  blobClient,
  inputContainerName,
  inputFilePaths);

Weitere Informationen zum Hochladen von Dateien als Blobs in ein Speicherkonto mit .NET finden Sie unter Schnellstart: Hochladen, Herunterladen und Auflisten von Blobs mit .NET.

Erstellen eines Pools mit Computeknoten

Als Nächstes erstellt das Beispiel im Batch-Konto durch Aufrufen von CreatePoolIfNotExistAsync einen Pool mit Computeknoten. In dieser definierten Methode wird die BatchClient.PoolOperations.CreatePool-Methode verwendet, um die Anzahl von Knoten, die VM-Größe und eine Poolkonfiguration festzulegen. Hier gibt ein VirtualMachineConfiguration-Objekt einen ImageReference-Verweis auf ein Windows Server-Image an, das im Azure Marketplace veröffentlicht wurde. Batch unterstützt viele verschiedene VM-Images im Azure Marketplace und auch benutzerdefinierte VM-Images.

Die Anzahl von Knoten und die VM-Größe werden mit definierten Konstanten festgelegt. Batch unterstützt dedizierte Knoten und Spot-Knoten, und Sie können entweder einen oder beide in Ihren Pools verwenden. Dedizierte Knoten sind für Ihren Pool reserviert. Spot-Knoten werden zu einem reduzierten Preis aus überschüssiger VM-Kapazität in Azure angeboten. Spot-Knoten sind nicht mehr verfügbar, wenn Azure nicht über genügend Kapazität verfügt. Das Beispiel erstellt standardmäßig einen Pool mit nur 5 Spot-Knoten der Größe Standard_A1_v2.

Hinweis

Überprüfen Sie Ihre Knotenkontingente. Eine Anleitung zum Erstellen einer Kontingentanforderung finden Sie unter Batch-Dienst – Kontingente und Limits.

Die Anwendung ffmpeg wird auf den Computeknoten bereitgestellt, indem der Poolkonfiguration ein ApplicationPackageReference-Element hinzugefügt wird.

Mit der CommitAsync-Methode wird der Pool an den Batch-Dienst übermittelt.

ImageReference imageReference = new ImageReference(
    publisher: "MicrosoftWindowsServer",
    offer: "WindowsServer",
    sku: "2016-Datacenter-smalldisk",
    version: "latest");

VirtualMachineConfiguration virtualMachineConfiguration =
    new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.windows amd64");

pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: DedicatedNodeCount,
    targetLowPriorityComputeNodes: LowPriorityNodeCount,
    virtualMachineSize: PoolVMSize,
    virtualMachineConfiguration: virtualMachineConfiguration);

pool.ApplicationPackageReferences = new List<ApplicationPackageReference>
    {
    new ApplicationPackageReference {
    ApplicationId = appPackageId,
    Version = appPackageVersion}};

await pool.CommitAsync();  

Erstellen eines Auftrags

Für einen Batch-Auftrag werden ein Pool zum Ausführen von Aufgaben und optionale Einstellungen wie eine Priorität und ein Zeitplan für die Arbeitsschritte angegeben. Im Beispiel wird ein Auftrag mit einem Aufruf von CreateJobAsync erstellt. In dieser definierten Methode wird die BatchClient.JobOperations.CreateJob-Methode zum Erstellen eines Auftrags in Ihrem Pool verwendet.

Mit der CommitAsync-Methode wird der Auftrag an den Batch-Dienst übermittelt. Der Auftrag enthält ursprünglich keine Aufgaben.

CloudJob job = batchClient.JobOperations.CreateJob();
job.Id = JobId;
job.PoolInformation = new PoolInformation { PoolId = PoolId };

await job.CommitAsync();

Erstellen von Aufgaben

Im Beispiel werden Aufgaben im Auftrag durch einen Aufruf der AddTasksAsync-Methode erstellt, mit der eine Liste mit CloudTask-Objekten erstellt wird. Für jede CloudTask wird ffmpeg ausgeführt, um ein ResourceFile-Eingabeobjekt per CommandLine-Eigenschaft zu verarbeiten. ffmpeg wurde zuvor bei der Erstellung des Pools auf jedem Knoten installiert. Hier wird in der Befehlszeile ffmpeg ausgeführt, um jede MP4-Eingabedatei (Video) in eine MP3-Datei (Audio) zu konvertieren.

Im Beispiel wird nach der Ausführung über die Befehlszeile ein OutputFile-Objekt für die MP3-Datei erstellt. Die Ausgabedateien (in diesem Fall eine Datei) jeder Aufgabe werden in einen Container im verknüpften Speicherkonto hochgeladen, indem die OutputFiles-Eigenschaft der Aufgabe verwendet wird. Früher im Codebeispiel wurde eine Shared Access Signature-URL (outputContainerSasUrl) abgerufen, um Schreibzugriff auf den Ausgabecontainer bereitzustellen. Beachten Sie die Bedingungen, die für das outputFile-Objekt festgelegt sind. Eine Ausgabedatei von einer Aufgabe wird nur in den Container hochgeladen, nachdem die Aufgabe erfolgreich abgeschlossen wurde (OutputFileUploadCondition.TaskSuccess). Weitere Implementierungsdetails finden Sie im vollständigen Codebeispiel auf GitHub.

Anschließend werden dem Auftrag im Beispiel mit der AddTaskAsync-Methode Aufgaben hinzugefügt und für die Ausführung auf den Computeknoten in die Warteschlange eingereiht.

Ersetzen Sie den Dateipfad der ausführbaren Datei durch den Namen der von Ihnen heruntergeladenen Version. In diesem Beispielcode wird das Beispiel ffmpeg-4.3.1-2020-11-08-full_buildverwendet.

 // Create a collection to hold the tasks added to the job.
List<CloudTask> tasks = new List<CloudTask>();

for (int i = 0; i < inputFiles.Count; i++)
{
    string taskId = String.Format("Task{0}", i);

    // Define task command line to convert each input file.
    string appPath = String.Format("%AZ_BATCH_APP_PACKAGE_{0}#{1}%", appPackageId, appPackageVersion);
    string inputMediaFile = inputFiles[i].FilePath;
    string outputMediaFile = String.Format("{0}{1}",
        System.IO.Path.GetFileNameWithoutExtension(inputMediaFile),
        ".mp3");
    string taskCommandLine = String.Format("cmd /c {0}\\ffmpeg-4.3.1-2020-09-21-full_build\\bin\\ffmpeg.exe -i {1} {2}", appPath, inputMediaFile, outputMediaFile);

    // Create a cloud task (with the task ID and command line)
    CloudTask task = new CloudTask(taskId, taskCommandLine);
    task.ResourceFiles = new List<ResourceFile> { inputFiles[i] };

    // Task output file
    List<OutputFile> outputFileList = new List<OutputFile>();
    OutputFileBlobContainerDestination outputContainer = new OutputFileBlobContainerDestination(outputContainerSasUrl);
    OutputFile outputFile = new OutputFile(outputMediaFile,
       new OutputFileDestination(outputContainer),
       new OutputFileUploadOptions(OutputFileUploadCondition.TaskSuccess));
    outputFileList.Add(outputFile);
    task.OutputFiles = outputFileList;
    tasks.Add(task);
}

// Add tasks as a collection
await batchClient.JobOperations.AddTaskAsync(jobId, tasks);
return tasks

Überwachen von Aufgaben

Wenn Batch einem Auftrag Aufgaben hinzufügt, werden sie vom Dienst automatisch in die Warteschlange eingereiht und für die Ausführung auf Computeknoten im zugeordneten Pool eingeplant. Basierend auf den Einstellungen, die Sie angeben, führt Batch das Einreihen, Planen und erneute Ausführen sowie andere Schritte der Aufgabenverwaltung aus.

Es gibt viele Ansätze für die Überwachung der Aufgabenausführung. In diesem Beispiel wird eine MonitorTasks-Methode definiert, mit der für Aufgaben nur der Abschluss und die fehlerhafte bzw. erfolgreiche Durchführung gemeldet wird. Im MonitorTasks-Code ist ein ODATADetailLevel-Element angegeben, um eine effiziente Auswahl von minimal erforderlichen Informationen zu den Aufgaben zu ermöglichen. Anschließend wird ein TaskStateMonitor-Element erstellt, mit dem Hilfsprogramme zum Überwachen von Aufgabenstatus bereitgestellt werden. Bei MonitorTasks wird im Beispiel gewartet, bis alle Aufgaben innerhalb eines bestimmten Zeitlimits den Status TaskState.Completed erreichen. Anschließend wird der Auftrag beendet, und es werden alle Aufgaben gemeldet, die zwar abgeschlossen wurden, aber für die ggf. ein Fehler wie „Exitcode ungleich null“ aufgetreten ist.

TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor();
try
{
    await taskStateMonitor.WhenAll(addedTasks, TaskState.Completed, timeout);
}
catch (TimeoutException)
{
    batchClient.JobOperations.TerminateJob(jobId);
    Console.WriteLine(incompleteMessage);
    return false;
}
batchClient.JobOperations.TerminateJob(jobId);
 Console.WriteLine(completeMessage);
...

Bereinigen von Ressourcen

Nach dem Ausführen der Aufgaben löscht die App den erstellten Eingabespeichercontainer automatisch und ermöglicht Ihnen das Löschen des Batch-Pools und -Auftrags. JobOperations und PoolOperations von BatchClient verfügen jeweils über entsprechende Löschmethoden, die aufgerufen werden, wenn Sie das Löschen bestätigen. Für die Aufträge und Aufgaben fallen zwar keine Kosten an, für Computeknoten dagegen schon. Daher empfehlen wir Ihnen, Pools nur bei Bedarf zuzuordnen. Beim Löschen des Pools werden alle Aufgabenausgaben auf den Knoten gelöscht. Die Ausgabedateien verbleiben aber im Speicherkonto.

Löschen Sie die Ressourcengruppe, das Batch-Konto und das Speicherkonto, wenn diese Elemente nicht mehr benötigt werden. Wählen Sie hierzu im Azure-Portal die Ressourcengruppe für das Batch-Konto aus, und klicken Sie auf Ressourcengruppe löschen.

Nächste Schritte

In diesem Tutorial haben Sie Folgendes gelernt:

  • Hinzufügen eines Anwendungspakets zu Ihrem Batch-Konto.
  • Authentifizieren mit Batch- und Storage-Konten.
  • Hochladen von Eingabedateien in Storage.
  • Erstellen eines Pools mit Computeknoten für die Ausführung einer Anwendung.
  • Erstellen eines Auftrags und von Aufgaben zum Verarbeiten von Eingabedateien.
  • Überwachen der Aufgabenausführung
  • Abrufen von Ausgabedateien.

Weitere Beispiele zur Verwendung der .NET-API zum Planen und Verarbeiten von Batch-Workloads finden Sie in den Batch C#-Beispielen auf GitHub.