Exercício – criar um conjunto de nós de computação para executar os nossos trabalhos

Concluído

Para executar um trabalho de lote, temos de adicionar um conjunto à nossa conta do Batch. Um conjunto contém nós de computação, que são os motores que executam o seu trabalho do Batch. Tem de especificar o número, tamanho e sistema operativo dos nós no momento da criação. Neste exercício, irá modificar a aplicação de consola que criou no exercício anterior para adicionar um conjunto à sua conta do Batch.

Sua empresa quer controlar os custos do aplicativo e pediu que você use um número fixo de nós.

Importante

Precisa da sua própria subscrição do Azure para executar este exercício e poderá incorrer em custos. Se ainda não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.

Adicionar definições ao novo conjunto

  1. No Cloud Shell, edite o ficheiro Program.cs no editor:

    code Program.cs
    
  2. Adicione as seguintes propriedades à classe Program em 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";
    

    As configurações anteriores são usadas no código para criar o pool. Olhando para cada variável, podemos explicá-las da seguinte forma:

    • PoolId: O nome que nosso código usa para fazer referência ao pool em outras chamadas de cliente em lote.
    • LowPriorityNodeCount: você criará um pool com três máquinas virtuais (VMs) de baixa prioridade.
    • PoolVMSize: As VMs serão STANDARD_A1_v2, o que dá aos nós 1 CPU, 2 GB de RAM e 10 GB de armazenamento SSD.
    • appPackageId: O nome do pacote de aplicativo a ser usado nos nós criados.
    • appPackageVersion: A versão do aplicativo a ser usada nos nós criados.

Atualize o método Main() para dar suporte a chamadas assíncronas

Iremos fazer várias chamadas assíncronas para serviços cloud, por isso a primeira coisa a fazer é tornar o Main assíncrono. Com a versão 7.1 e posterior do C# .NET, são suportados os métodos Main assíncronos nas aplicações de consola.

  1. Altere o aplicativo de console para permitir chamadas de método assíncrono, adicionando primeiro a System.Threading.Tasks biblioteca.

    using System.Threading.Tasks;
    using System.Collections.Generic; // Also add generics to allow the app to use Lists
    
  2. Em seguida, atualize a assinatura do método Main da seguinte forma:

    static async Task Main(string[] args)
    

Criar um conjunto

  1. Adicione o seguinte novo método à classe Program para criar um conjunto do Batch. O método:

    • Cria um objeto de referência de imagem para armazenar as configurações dos nós a serem adicionados ao pool.
    • Usa a referência de imagem para criar um VirtualMachineConfiguration objeto.
    • Cria um pool não acoplado usando as propriedades declaradas anteriormente e o VirtualMachineConfiguration.
    • Adiciona uma referência de pacote de aplicativo ao pool.
    • Cria o pool no Azure.
    • Usa dois parâmetros, o batchClient e PoolId.
      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
                }
            }
        }  
    
  2. Ligue CreateBatchPoolAsync a partir do nosso Main método. O método Main deve ser o seguinte:

    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);
    }
    

Testar a aplicação

  1. No editor de códigos, clique com o botão direito do mouse e selecione Salvar, clique com o botão direito do mouse e selecione Sair.

  2. No Cloud Shell, compile e execute o aplicativo com o seguinte comando:

    dotnet run
    
  3. O aplicativo levará alguns minutos para ser executado, e você deve obter a seguinte saída:

    URL: <your batch account url, Name: <your batch name>, Key: <your batch key>
    Creating pool [WinFFmpegPool]...
    

Lembre-se de que cada nó é uma VM a executar o Windows Server 2012, com apenas uma CPU e 2 GB de RAM. Demora algum tempo para o Batch transferir essas imagens da VM do Windows do Azure Marketplace, criar a rede e infraestrutura da VM e, por fim, iniciar cada nó. Esta é a parte mais demorada da maioria das soluções do Batch. Um fluxo de trabalho normal do Batch não limpa o conjunto e os nós.