Inicio rápido: usar .NET para crear un grupo de Batch y ejecutar un trabajo

Este inicio rápido muestra cómo comenzar a usar Azure Batch mediante la ejecución de una aplicación C# que usa la API .NET para Azure Batch. La aplicación .NET:

  • Carga varios archivos de datos de entrada en un contenedor de blobs de Azure Storage para usarlos para el procesamiento de tareas de Batch.
  • Crea un grupo de dos máquinas virtuales (VM) o nodos de ejecución que ejecutan Windows Server.
  • Crea un trabajo que ejecuta tareas en los nodos para procesar cada archivo de entrada con una línea de comandos de Windows.
  • Muestra los archivos de salida que devuelven las tareas.

Tras completar este artículo de inicio rápido, comprenderás los conceptos clave del servicio Batch y estarás listo para usar dicho servicio con cargas de trabajo más realistas y a mayor escala.

Requisitos previos

Ejecución de la aplicación

Para completar este inicio rápido, descargue o clone la aplicación, proporcione los valores de la cuenta, compile y ejecute la aplicación, y verifique el resultado.

Descargar o clonar la aplicación

Descargue o clone la aplicación Azure Batch .NET Quickstart desde GitHub. Usa el siguiente comando para clonar el repositorio de aplicaciones con un cliente de Git:

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

Proporciona la información de tu cuenta

La aplicación debe usar los nombres de cuenta de Batch y Storage, los valores de clave de cuenta y el punto de conexión de la cuenta de Batch. Puedes obtener esta información de las herramientas de Azure Portal, API de Azure o de línea de comandos.

Para obtener la información de la cuenta del Azure Portal:

  1. En la barra de Azure Search, busca y selecciona el nombre de la cuenta de Batch.
  2. En la página Cuenta de Batch, selecciona Claves en el panel de navegación izquierdo.
  3. En la página Claves, copia los valores siguientes:
  • Cuenta de Batch
  • Punto de conexión de la cuenta
  • Clave de acceso principal
  • Nombre de cuenta de almacenamiento
  • Key1

Vaya a la carpeta batch-dotnet-quickstart descargada y edite las cadenas de credenciales en Program.cs para proporcionar los valores que ha copiado:

// Batch account credentials
private const string BatchAccountName = "<batch account>";
private const string BatchAccountKey  = "<primary access key>";
private const string BatchAccountUrl  = "<account endpoint>";

// Storage account credentials
private const string StorageAccountName = "<storage account name>";
private const string StorageAccountKey  = "<key1>

Importante

No se recomienda exponer las claves de cuenta en el origen de la aplicación para el uso de producción. Debes restringir el acceso a las credenciales y hacer referencia a ellas en tu código mediante el uso de variables o un archivo de configuración. Es mejor almacenar claves de cuenta de Batch y Storage en Azure Key Vault.

Compilación y ejecución de la aplicación, y visualización de la salida

Para ver el flujo de trabajo de Batch en acción, compile y ejecute la aplicación en Visual Studio. También puede usar los comandos dotnet build y dotnet run de la línea de comandos.

En Visual Studio:

  1. Abra el archivo BatchDotNetQuickstart.sln, haga clic con el botón derecho en la solución en Explorador de soluciones y seleccione Compilar. Si se le solicita, use el Administrador de paquetes NuGet para actualizar o restaurar paquetes NuGet.

  2. Después de que finalice la compilación, seleccione BatchDotNetQuickstart en la barra de menú superior para ejecutar la aplicación.

El tiempo de ejecución típico con la configuración predeterminada es de aproximadamente cinco minutos. La configuración inicial del nodo del grupo lleva la mayor parte del tiempo. Para volver a ejecutar el trabajo, elimínelo de la ejecución anterior, pero no elimine el grupo. En un grupo preconfigurado, el trabajo se completa en pocos segundos.

La aplicación devuelve un resultado similar al siguiente ejemplo:

Sample start: 11/16/2022 4:02:54 PM

Container [input] created.
Uploading file taskdata0.txt to container [input]...
Uploading file taskdata1.txt to container [input]...
Uploading file taskdata2.txt to container [input]...
Creating pool [DotNetQuickstartPool]...
Creating job [DotNetQuickstartJob]...
Adding 3 tasks to job [DotNetQuickstartJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...

Hay una pausa en Monitoring all tasks for 'Completed' state, timeout in 00:30:00... mientras se inician los nodos de cómputo del grupo. A medida que se crean las tareas, Batch las pone en cola para que se ejecuten en el grupo. Tan pronto como el primer nodo de cómputo esté disponible, la primera tarea se ejecuta en el nodo. Puedes supervisar el estado del nodo, la tarea y el trabajo desde la página de tu cuenta de Batch en Azure Portal.

Una vez completada cada tarea, verás una salida similar a la del ejemplo siguiente:

Printing task output.
Task: Task0
Node: tvm-2850684224_3-20171205t000401z
Standard out:
Batch processing began with mainframe computers and punch cards. Today it still plays a central role...
stderr:
...

Revisión del código

Revise el código para comprender los pasos de Azure Batch .NET Quickstart.

Crear clientes de servicio y cargar archivos de recursos

  1. Para interactuar con la cuenta de almacenamiento, la aplicación usa la biblioteca cliente de blobs de Azure Storage para .NET para crear un BlobServiceClient.

    var sharedKeyCredential = new StorageSharedKeyCredential(storageAccountName, storageAccountKey);
    string blobUri = "https://" + storageAccountName + ".blob.core.windows.net";
    
    var blobServiceClient = new BlobServiceClient(new Uri(blobUri), sharedKeyCredential);
    return blobServiceClient;
    
  2. La aplicación usa la referencia blobServiceClient para crear un contenedor en la cuenta de almacenamiento y cargar archivos de datos en el contenedor. Los archivos de almacenamiento se definen como objetos ResourceFile de Batch para que el servicio los descargue después a los nodos de ejecución.

    List<string> inputFilePaths = new()
    {
        "taskdata0.txt",
        "taskdata1.txt",
        "taskdata2.txt"
    };
    
    var inputFiles = new List<ResourceFile>();
    
    foreach (var filePath in inputFilePaths)
    {
        inputFiles.Add(UploadFileToContainer(containerClient, inputContainerName, filePath));
    }
    
  3. La aplicación crea un objeto BatchClient para crear y administrar los grupos, los trabajos y las tareas de Batch. El cliente de Batch utiliza autenticación de clave compartida. Batch también admite la autenticación de Microsoft Entra.

    var cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);
    
     using BatchClient batchClient = BatchClient.Open(cred);
    ...
    

Creación de un grupo de nodos de proceso

Para crear un grupo de Batch, la aplicación usa el método BatchClient.PoolOperations.CreatePool para establecer el número de nodos, el tamaño de la máquina virtual y la configuración del grupo. El siguiente objeto VirtualMachineConfiguration especifica una ImageReference a una imagen de Windows Server Marketplace. Batch admite una amplia gama de imágenes de los sistemas operativos Linux y Windows Server del Marketplace, y también admite imágenes de VM personalizadas.

El PoolNodeCount y el tamaño de máquina virtual PoolVMSize son constantes definidas. La aplicación crea un grupo de dos nodos Standard_A1_v2. Este tamaño ofrece un buen equilibrio entre rendimiento y coste para este artículo de inicio rápido.

El método Commit envía el grupo al servicio Batch.


private static VirtualMachineConfiguration CreateVirtualMachineConfiguration(ImageReference imageReference)
{
    return new VirtualMachineConfiguration(
        imageReference: imageReference,
        nodeAgentSkuId: "batch.node.windows amd64");
}

private static ImageReference CreateImageReference()
{
    return new ImageReference(
        publisher: "MicrosoftWindowsServer",
        offer: "WindowsServer",
        sku: "2016-datacenter-smalldisk",
        version: "latest");
}

private static void CreateBatchPool(BatchClient batchClient, VirtualMachineConfiguration vmConfiguration)
{
    try
    {
        CloudPool pool = batchClient.PoolOperations.CreatePool(
            poolId: PoolId,
            targetDedicatedComputeNodes: PoolNodeCount,
            virtualMachineSize: PoolVMSize,
            virtualMachineConfiguration: vmConfiguration);

        pool.Commit();
    }
...

Creación de un trabajo de Batch

Un trabajo de Batch es una agrupación lógica de una o varias tareas. El trabajo incluye valores comunes para las tareas, como la prioridad y el grupo en el que se ejecutan las tareas.

La aplicación usa el método BatchClient.JobOperations.CreateJob para crear un trabajo en el grupo. El método Commit envía el trabajo al servicio Batch. Inicialmente, el trabajo no tiene tareas.

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

    job.Commit();
}
...

Creación de tareas

Batch proporciona varias formas de implementar aplicaciones y scripts en nodos de proceso. Esta aplicación crea una lista de objetos de entrada ResourceFile de CloudTask. Cada tarea procesa un archivo de entrada mediante una propiedad CommandLine. La línea de comandos de Batch es el lugar en el que se especifica la aplicación o el script.

En el siguiente código, la línea de comandos ejecuta el comando type de Windows para mostrar los archivos de entrada. Luego, la aplicación agrega cada tarea al trabajo con el método AddTask, que las pone en cola para que se ejecuten en los nodos de ejecución.

for (int i = 0; i < inputFiles.Count; i++)
{
    string taskId = String.Format("Task{0}", i);
    string inputFilename = inputFiles[i].FilePath;
    string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);

    var task = new CloudTask(taskId, taskCommandLine)
    {
        ResourceFiles = new List<ResourceFile> { inputFiles[i] }
    };
    tasks.Add(task);
}

batchClient.JobOperations.AddTask(JobId, tasks);

Visualización de la salida de la tarea

La aplicación crea TaskStateMonitor que supervisa las tareas y asegura que se completen. Tras la ejecución correcta de cada tarea, la salida se escribe en stdout.txt. Luego, la aplicación usa la propiedad CloudTask.ComputeNodeInformation para mostrar el archivo stdout.txt que genera cada tarea que se completa.

foreach (CloudTask task in completedtasks)
{
    string nodeId = String.Format(task.ComputeNodeInformation.ComputeNodeId);
    Console.WriteLine("Task: {0}", task.Id);
    Console.WriteLine("Node: {0}", nodeId);
    Console.WriteLine("Standard out:");
    Console.WriteLine(task.GetNodeFile(Constants.StandardOutFileName).ReadAsString());
}

Limpieza de recursos

La aplicación elimina automáticamente el contenedor de almacenamiento que crea y ofrece la opción de eliminar el grupo y el trabajo de Batch. Los grupos y nodos incurren en cargos mientras se ejecutan los nodos, incluso si no ejecutan trabajos. Si ya no necesitas el grupo, elimínalo.

Cuando ya no necesite la cuenta de Batch ni la cuenta de almacenamiento, puede eliminar el grupo de recursos que los contiene. En Azure Portal, selecciona Eliminar grupo de recursos en la parte superior de la página del grupo de recursos. En la pantalla Eliminar un grupo de recursos, escribe el nombre del grupo de recursos y luego selecciona Eliminar.

Pasos siguientes

En este inicio rápido, ha ejecutado una aplicación que usa la API de .NET de Batch para crear un grupo, nodos, trabajos y tareas de Batch. El trabajo cargó archivos de recursos en un contenedor de almacenamiento, ejecutó tareas en los nodos y mostró la salida de los nodos.

Ahora que conoces los conceptos clave del servicio Batch, ya estás listo para usar Batch con cargas de trabajo más realistas y a mayor escala. Para más información acerca de Azure Batch y examinar una carga de trabajo en paralelo con una aplicación real, vaya al tutorial de .NET de Batch.