Introdução ao SDK do Batch para JavaScript

Aprenda as noções básicas da criação de um cliente do Batch em JavaScript com Azure Batch SDK JavaScript. Tomamos uma abordagem passo a passo para compreender um cenário para uma aplicação de lote e, em seguida, configurá-la com JavaScript.

Pré-requisitos

Este artigo pressupõe que tem conhecimentos práticos sobre JavaScript e familiaridade com o Linux. Também parte do princípio de que tem uma conta do Azure configurada com direitos de acesso para criar serviços do Batch e de Armazenamento.

Antes de seguir os passos descritos neste artigo, recomendamos ler a Descrição Geral Técnica do Azure Batch.

Compreender o cenário

Aqui, temos um script simples escrito em Python que transfere todos os ficheiros csv de um contentor de armazenamento de Blobs do Azure e os converte em JSON. Para processar em paralelo vários contentores da conta de armazenamento, podemos implementar o script como uma tarefa do Azure Batch.

arquitetura de Azure Batch

O diagrama seguinte mostra como podemos dimensionar o script python com Azure Batch e um cliente.

Diagrama a mostrar a arquitetura do cenário.

O exemplo de JavaScript implementa uma tarefa de lote com uma tarefa de preparação (explicada em detalhe mais tarde) e um conjunto de tarefas consoante o número de contentores na conta de armazenamento. Pode transferir os scripts a partir do repositório do GitHub.

Dica

O exemplo de JavaScript na ligação especificada não contém código específico a ser implementado como uma aplicação de funções do Azure. Para saber como criar uma aplicação destas, pode ver as ligações seguintes:

Criar a aplicação

Agora, vamos seguir o processo passo a passo para criar o cliente JavaScript:

Passo 1: Instalar o SDK do Azure Batch

Pode instalar Azure Batch SDK para JavaScript com o comando de instalação npm.

npm install @azure/batch

Este comando instala a versão mais recente do SDK JavaScript do azure-batch.

Dica

Numa aplicação de função das Funções do Azure, pode aceder à “Consola Kudu”, no separador Definições da aplicação das Funções do Azure, para executar os comandos npm install. Neste caso, para instalar Azure Batch SDK para JavaScript.

Passo 2: Criar uma conta do Azure Batch

Pode criá-la a partir do portal do Azure ou da linha de comandos (CLI do Azure do PowerShell /).

Seguem-se os comandos para criar a conta com a CLI do Azure.

Crie um Grupo de Recursos; ignore este passo se já tiver um no qual queira criar a conta do Batch:

az group create -n "<resource-group-name>" -l "<location>"

Depois, crie uma conta do Azure Batch.

az batch account create -l "<location>" -g "<resource-group-name>" -n "<batch-account-name>"

Cada conta do Batch tem chaves de acesso correspondentes. Estas chaves são necessárias para criar mais recursos nessas contas. Uma boa prática para ambientes de produção consiste em armazenar estas chaves no Azure Key Vault. Depois, pode criar um Principal de serviço para a aplicação. Ao utilizar este principal de serviço, a aplicação pode criar um token OAuth para aceder às chaves no cofre de chaves.

az batch account keys list -g "<resource-group-name>" -n "<batch-account-name>"

Copie e armazene a chave, para utilizá-la nos passos subsequentes.

Passo 3: Criar um cliente do serviço Azure Batch

O fragmento de código seguinte importa primeiro o módulo JavaScript do azure-batch e, em seguida, cria um cliente do Serviço Batch. Em primeiro lugar, tem de criar um objeto SharedKeyCredentials com a chave da conta do Batch copiada do passo anterior.

// Initializing Azure Batch variables

import { BatchServiceClient, BatchSharedKeyCredentials } from "@azure/batch";

// Replace values below with Batch Account details
const batchAccountName = '<batch-account-name>';
const batchAccountKey = '<batch-account-key>';
const batchEndpoint = '<batch-account-url>';

const credentials = new BatchSharedKeyCredentials(batchAccountName, batchAccountKey);
const batchClient = new BatchServiceClient(credentials, batchEndpoint);

O URI do Azure Batch está disponível no separador Descrição Geral do portal do Azure. Tem o formato seguinte:

https://accountname.location.batch.azure.com

Veja a captura de ecrã:

URI do Azure Batch

Passo 4: Criar um conjunto do Azure Batch

Os conjuntos do Azure Batch consistem em várias VMs (também conhecidas como Nós do Batch). O serviço do Azure Batch implementa a tarefa nestes nós e gere-as. Pode definir os seguintes parâmetros de configuração para o conjunto.

  • Tipo de imagem das Máquinas Virtuais
  • Tamanho dos nós de Máquinas Virtuais
  • Número de nós de Máquinas Virtuais

Dica

O tamanho e o número dos nós de máquinas virtuais depende muito do número de tarefas que quer executar em paralelo e também das próprias tarefas. Para determinar o tamanho e o número ideais, recomendamos que faça testes.

O fragmento de código seguinte cria os objetos do parâmetro de configuração.

// Creating Image reference configuration for Ubuntu Linux VM
const imgRef = {
    publisher: "Canonical",
    offer: "UbuntuServer",
    sku: "20.04-LTS",
    version: "latest"
}
// Creating the VM configuration object with the SKUID
const vmConfig = {
    imageReference: imgRef,
    nodeAgentSKUId: "batch.node.ubuntu 20.04"
};
// Number of VMs to create in a pool
const numVms = 4;

// Setting the VM size
const vmSize = "STANDARD_D1_V2";

Dica

Para obter a lista de imagens de VMs do Linux disponíveis para o Azure Batch e IDs dos respetivos SKUs, veja List of virtual machine images (Lista de imagens de máquinas virtuais).

Depois de definida a configuração do conjunto, pode criar o conjunto do Azure Batch. O comando Batch pool cria os nós de Máquinas Virtuais e prepara-os para receberem tarefas a executar. Cada conjunto deve ter um ID único para referência em passos subsequentes.

O fragmento de código seguinte cria um conjunto do Azure Batch.

// Create a unique Azure Batch pool ID
const now = new Date();
const poolId = `processcsv_${now.getFullYear()}${now.getMonth()}${now.getDay()}${now.getHours()}${now.getSeconds()}`;

const poolConfig = {
    id: poolId,
    displayName: "Processing csv files",
    vmSize: vmSize,
    virtualMachineConfiguration: vmConfig,
    targetDedicatedNodes: numVms,
    enableAutoScale: false
};

// Creating the Pool
var pool = batchClient.pool.add(poolConfig, function (error, result){
    if(error!=null){console.log(error.response)};
});

Pode verificar o estado do conjunto criado e garantir que o estado está “ativo” antes de avançar para a submissão de uma Tarefa para o mesmo.

var cloudPool = batchClient.pool.get(poolId,function(error,result,request,response){
        if(error == null)
        {

            if(result.state == "active")
            {
                console.log("Pool is active");
            }
        }
        else
        {
            if(error.statusCode==404)
            {
                console.log("Pool not found yet returned 404...");

            }
            else
            {
                console.log("Error occurred while retrieving pool data");
            }
        }
        });

Segue-se um objeto de resultado de exemplo devolvido pela função pool.get.

{
  id: 'processcsv_2022002321',
  displayName: 'Processing csv files',
  url: 'https://<batch-account-name>.westus.batch.azure.com/pools/processcsv_2022002321',
  eTag: '0x8D9D4088BC56FA1',
  lastModified: 2022-01-10T07:12:21.943Z,
  creationTime: 2022-01-10T07:12:21.943Z,
  state: 'active',
  stateTransitionTime: 2022-01-10T07:12:21.943Z,
  allocationState: 'steady',
  allocationStateTransitionTime: 2022-01-10T07:13:35.103Z,
  vmSize: 'standard_d1_v2',
  virtualMachineConfiguration: {
    imageReference: {
      publisher: 'Canonical',
      offer: 'UbuntuServer',
      sku: '20.04-LTS',
      version: 'latest'
    },
    nodeAgentSKUId: 'batch.node.ubuntu 20.04'
  },
  resizeTimeout: 'PT15M',
  currentDedicatedNodes: 4,
  currentLowPriorityNodes: 0,
  targetDedicatedNodes: 4,
  targetLowPriorityNodes: 0,
  enableAutoScale: false,
  enableInterNodeCommunication: false,
  taskSlotsPerNode: 1,
  taskSchedulingPolicy: { nodeFillType: 'Spread' }}

Passo 4: Submeter uma tarefa do Azure Batch

As tarefas do Azure Batch são grupos lógicos de tarefas semelhantes. No nosso cenário, é "Processar csv para JSON". Cada tarefa aqui pode estar a processar ficheiros csv presentes em cada contentor do Armazenamento do Azure.

Estas tarefas serão executadas em paralelo e implementadas em vários nós, orquestradas pelo serviço Azure Batch.

Dica

Pode utilizar a propriedade taskSlotsPerNode para especificar o número máximo de tarefas que podem ser executadas simultaneamente num único nó.

Tarefa de preparação

Os nós de VMs criados são nós Ubuntu vazios. Muitas vezes, tem de instalar um conjunto de programas como pré-requisitos. Normalmente, relativamente a nós do Linux, pode ser um script de shell que instala os pré-requisitos antes de a tarefa em si ser executada. No entanto, pode ser qualquer executável programável.

O script da shell neste exemplo instala o Python-pip e o SDK do Blob de Armazenamento do Azure para Python.

Pode carregar o script numa conta de Armazenamento do Azure e gerar um URI de SAS para aceder ao mesmo. Este processo também pode ser automatizado com o SDK JavaScript do Armazenamento do Azure.

Dica

As tarefas de preparação para tarefas só são executadas nos nós de VMs, nos quais essas tarefas específicas têm de ser executadas. Se quiser instalar pré-requisitos em todos os nós, independentemente das tarefas que são executadas nos mesmos, pode utilizar a propriedade startTask enquanto estiver a adicionar um conjunto. Pode utilizar a definição de tarefa de preparação seguinte como referência.

As tarefas de preparação são especificadas durante a submissão do trabalho do Azure Batch. Seguem-se alguns parâmetros de tarefa de preparação configuráveis:

  • ID: um identificador exclusivo para a tarefa de preparação
  • commandLine: a linha de comandos para executar o executável da tarefa
  • resourceFiles: matriz de objetos que disponibiliza detalhes dos ficheiros que têm de ser transferidos para que esta tarefa seja executada. Seguem-se as respetivas opções
    • httpUrl: o URL do ficheiro a transferir
    • filePath: o caminho local para transferir e guardar o ficheiro
    • fileMode: aplicável apenas a nós do Linux, o fileMode está no formato octal e tem o valor predefinido 0770
  • waitForSuccess: se definido como verdadeiro, a tarefa não é executada em falhas da tarefa de preparação
  • runElevated: defina como verdadeiro, se forem necessários privilégios elevados para executar a tarefa.

O fragmento de código seguinte mostra o exemplo de configuração de script de tarefa de preparação:

var jobPrepTaskConfig = {id:"installprereq",commandLine:"sudo sh startup_prereq.sh > startup.log",resourceFiles: [{ 'httpUrl': 'Blob sh url', 'filePath': 'startup_prereq.sh' }],waitForSuccess:true,runElevated:true, userIdentity: {autoUser: {elevationLevel: "admin", scope: "pool"}}}

Se não for necessário instalar pré-requisitos para que as tarefas sejam executadas, pode ignorar as tarefas de preparação. O código seguinte cria um trabalho com o nome a apresentar “process csv files."

// Setting Batch Pool ID
const poolInfo = { poolId: poolId };
// Batch job configuration object
const jobId = "processcsvjob";
const jobConfig = {
    id: jobId,
    displayName: "process csv files",
    jobPreparationTask: jobPrepTaskConfig,
    poolInfo: poolInfo
};
// Adding Azure batch job to the pool
const job = batchClient.job.add(jobConfig, function (error, result) {
        if (error !== null) {
            console.log("An error occurred while creating the job...");
            console.log(error.response);
        }
    }
);

Passo 5: Submeter tarefas do Azure Batch para trabalhos

Agora que o trabalho “process csv” está criado, vamos criar tarefas para o mesmo. Partindo do princípio de que temos quatro contentores, temos de criar quatro tarefas, uma para cada contentor.

Se olharmos para o script de Python, este aceita dois parâmetros:

  • nome do contentor: o contentor do Armazenamento a partir do qual transferir ficheiros
  • padrão: um parâmetro opcional do padrão de nomenclatura do ficheiro

Partindo do princípio de que temos quatro contentores "con1", "con2", "con3", "con4", o código seguinte mostra a submissão de quatro tarefas para a tarefa de lote do Azure "process csv" que criámos anteriormente.

// storing container names in an array
const containerList = ["con1", "con2", "con3", "con4"];      //Replace with list of blob containers within storage account
containerList.forEach(function (val, index) {
    console.log("Submitting task for container : " + val);
    const containerName = val;
    const taskID = containerName + "_process";
    // Task configuration object
    const taskConfig = {
        id: taskID,
        displayName: 'process csv in ' + containerName,
        commandLine: 'python processcsv.py --container ' + containerName,
        resourceFiles: [{ 'httpUrl': 'Blob script url', 'filePath': 'processcsv.py' }]
    };

    const task = batchClient.task.add(jobId, taskConfig, function (error, result) {
        if (error !== null) {
            console.log("Error occurred while creating task for container " + containerName + ". Details : " + error.response);
        }
        else {
            console.log("Task for container : " + containerName + " submitted successfully");
        }
    });
});

O código adiciona várias tarefas ao conjunto e cada uma das tarefas é executada num nó no conjunto de VMs criado. Se o número de tarefas exceder o número de VMs num conjunto ou a propriedade taskSlotsPerNode, as tarefas aguardam até que um nó seja disponibilizado. Esta orquestração é processada pelo Azure Batch automaticamente.

O portal tem vistas detalhadas sobre as tarefas e os estados dos trabalhos. Também pode utilizar a lista e obter funções no SDK JavaScript do Azure. Estão disponíveis detalhes na ligação da documentação.

Passos seguintes