Ejercicio: Creación de un grupo de nodos de proceso para ejecutar los trabajos
Para ejecutar un trabajo por lotes, es necesario agregar un grupo a la cuenta de Batch. Un grupo contiene nodos de proceso, que son los motores que ejecutan el trabajo de Batch. El número, el tamaño y el sistema operativo de los nodos se especifican en tiempo de creación. En este ejercicio, modificará la aplicación de consola que ha creado en el anterior para agregar un grupo a la cuenta de Batch.
Su empresa quiere controlar los costes de la aplicación y le pidió que use un número fijo de nodos.
Importante
Para realizar este ejercicio, se necesita una suscripción de Azure propia y puede que se apliquen cargos. Si aún no tiene una suscripción de Azure, cree una cuenta gratuita antes de comenzar.
Adición de configuración para el nuevo grupo
En Cloud Shell, modifique el archivo
Program.cs
en el editor:code Program.cs
Agregue las propiedades siguientes a la clase Program de Program.cs:
private const string PoolId = "WinFFmpegPool"; private const int DedicatedNodeCount = 0; private const int LowPriorityNodeCount = 3; private const string PoolVMSize = "STANDARD_D2_v2"; private const string appPackageId = "ffmpeg"; private const string appPackageVersion = "3.4";
La configuración anterior se usa en el código para crear el grupo. Al examinar cada variable se pueden explicar como se muestra a continuación:
- PoolId: Nombre que usará el código para hacer referencia al grupo en otras llamadas de cliente de Batch.
- LowPriorityNodeCount: Creará un grupo con tres máquinas virtuales (VM) de prioridad baja.
- PoolVMSize: Las máquinas virtuales serán STANDARD_A1_v2, lo que proporciona a los nodos 1 CPU, 2 GB de RAM y 10 GB de almacenamiento SSD.
- appPackageId: Nombre del paquete de aplicación que se usará en los nodos que se creen.
- appPackageVersion: Versión de la aplicación que se usará en los nodos que se creen.
Actualización del método Main() para admitir llamadas asincrónicas
Se realizarán varias llamadas asincrónicas a servicios en la nube, por lo que el primer paso consiste en convertir Main
en asincrónico. Con la versión 7.1 de .NET para C# y posteriores, se admiten métodos Main
asincrónicos en las aplicaciones de consola.
Para cambiar la aplicación de consola para permitir llamadas de método asincrónicas, agregue primero la biblioteca
System.Threading.Tasks
.using System.Threading.Tasks; using System.Collections.Generic; // Also add generics to allow the app to use Lists
A continuación, actualice la firma del método
Main
como sigue:static async Task Main(string[] args)
Creación de un grupo
Agregue el siguiente método nuevo a la clase Program para crear un grupo de Batch. El método realiza las acciones siguientes:
- Crea un objeto de referencia de imagen para almacenar la configuración de los nodos que se vayan a agregar al grupo.
- Usa la referencia de imagen para crear un objeto
VirtualMachineConfiguration
. - Crea un grupo sin enlazar con las propiedades declaradas anteriormente y
VirtualMachineConfiguration
. - Agrega una referencia de paquete de aplicación al grupo.
- Crea el grupo en Azure.
- Requiere dos parámetros,
batchClient
yPoolId
.
private static async Task CreateBatchPoolAsync(BatchClient batchClient, string poolId) { CloudPool pool = null; Console.WriteLine("Creating pool [{0}]...", poolId); // Create an image reference object to store the settings for the nodes to be added to the pool ImageReference imageReference = new ImageReference( publisher: "MicrosoftWindowsServer", offer: "WindowsServer", sku: "2012-R2-Datacenter-smalldisk", version: "latest"); // Use the image reference to create a VirtualMachineConfiguration object VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration( imageReference: imageReference, nodeAgentSkuId: "batch.node.windows amd64"); try { // Create an unbound pool. No pool is actually created in the Batch service until we call // CloudPool.CommitAsync(). This CloudPool instance is therefore considered "unbound," and we can // modify its properties. pool = batchClient.PoolOperations.CreatePool( poolId: poolId, targetDedicatedComputeNodes: DedicatedNodeCount, targetLowPriorityComputeNodes: LowPriorityNodeCount, virtualMachineSize: PoolVMSize, virtualMachineConfiguration: virtualMachineConfiguration); // Specify the application and version to install on the compute nodes pool.ApplicationPackageReferences = new List<ApplicationPackageReference> { new ApplicationPackageReference { ApplicationId = appPackageId, Version = appPackageVersion } }; // Create the pool await pool.CommitAsync(); } catch (BatchException be) { // Accept the specific error code PoolExists as that is expected if the pool already exists if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.PoolExists) { Console.WriteLine("The pool [{0}] already existed when we tried to create it", poolId); } else { throw; // Any other exception is unexpected } } }
Llame a
CreateBatchPoolAsync
desde el métodoMain
. Ahora el método Main debe ser el siguiente:static async Task Main(string[] args) { // Read the environment variables to allow the app to connect to the Azure Batch account batchAccountUrl = Environment.GetEnvironmentVariable(envVarBatchURI); batchAccountName = Environment.GetEnvironmentVariable(envVarBatchName); batchAccountKey = Environment.GetEnvironmentVariable(envVarKey); // Show the user the batch the app is attaching to Console.WriteLine("URL: {0}, Name: {1}, Key: {2}", batchAccountUrl, batchAccountName, batchAccountKey); // The batch client requires a BatchSharedKeyCredentials object to open a connection var sharedKeyCredentials = new BatchSharedKeyCredentials(batchAccountUrl, batchAccountName, batchAccountKey); var batchClient = BatchClient.Open(sharedKeyCredentials); // Create the Batch pool, which contains the compute nodes that execute tasks. await CreateBatchPoolAsync(batchClient, PoolId); }
Prueba de la aplicación
En el editor de código, haga clic con el botón derecho y seleccione Guardar y, a continuación, haga clic con el botón derecho y seleccione Salir.
En Cloud Shell, compile y ejecute la aplicación con el comando siguiente:
dotnet run
La aplicación tardará unos minutos en ejecutarse y debería obtener la siguiente salida:
URL: <your batch account url, Name: <your batch name>, Key: <your batch key> Creating pool [WinFFmpegPool]...
Recuerde que cada nodo es una máquina virtual que ejecuta un servidor Windows 2012, con solo una CPU y 2 GB de RAM. Batch tarda tiempo en transferir esas imágenes de máquina virtual Windows desde el Marketplace de máquinas virtuales de Azure, crear la infraestructura de máquinas virtuales y redes, y por último, iniciar cada nodo. Esta es la parte más lenta de la mayoría de las soluciones de Batch. Un flujo de trabajo típico de Batch no limpia el grupo y sus nodos.