Partilhar via


Como utilizar o Armazenamento de Filas a partir de Java

Descrição Geral

Este guia irá mostrar-lhe como codificar cenários comuns com o serviço Armazenamento de Filas do Azure. Os exemplos são escritos em Java e utilizam Azure Storage SDK for Java (SDK do Armazenamento do Azure para Java). Os cenários incluem inserir, pré-visualizar, obter e eliminar mensagens de fila. O código para criar e eliminar filas também é abrangido. Para obter mais informações sobre filas, consulte a secção Passos seguintes .

O que é o Armazenamento de filas?

O Armazenamento de Filas do Azure é um serviço para armazenar um grande número de mensagens que podem ser acedidas a partir de qualquer local no mundo através de chamadas autenticadas com HTTP ou HTTPS. Uma mensagem de fila única pode ter até 64 KB e uma fila pode conter milhões de mensagens, até ao limite da capacidade total de uma conta de armazenamento. O armazenamento de filas é frequentemente utilizado para criar um registo de tarefas pendentes para processar de forma assíncrona.

Conceitos de serviço de fila

O serviço Fila do Azure contém os seguintes componentes:

Componentes do serviço fila do Azure

  • Conta de Armazenamento: todos os acessos ao Storage do Azure são efetuados através de uma conta de armazenamento. Para obter mais informações sobre contas de armazenamento, veja Descrição geral da conta de armazenamento.

  • Fila: uma fila contém um conjunto de mensagens. Todas as mensagens têm de estar numa fila. Tenha em atenção que o nome da fila tem de estar todo em minúsculas. Para obter informações sobre a nomenclatura de filas, veja Nomenclatura de Filas e Metadados.

  • Mensagem: uma mensagem, em qualquer formato, até 64 KB. O tempo máximo que uma mensagem pode permanecer na fila de espera é de 7 dias. Para a versão 2017-07-29 ou posterior, o tempo máximo de vida pode ser qualquer número positivo ou -1 que indique que a mensagem não expira. Se este parâmetro for omitido, o tempo de vida predefinido é de sete dias.

  • Formato de URL: As filas são endereçáveis com o seguinte formato de URL: http://<storage account>.queue.core.windows.net/<queue>

    O seguinte URL endereça uma fila no diagrama:

    http://myaccount.queue.core.windows.net/incoming-orders

Criar uma conta de armazenamento do Azure

A forma mais fácil de criar a primeira conta de armazenamento do Azure é com o portal do Azure. Para saber mais, veja Criar uma conta de armazenamento.

Também pode utilizar o Azure PowerShell, a CLI do Azure ou o Fornecedor de Recursos do Armazenamento do Azure para .NET.

Se preferir não criar uma conta de armazenamento no Azure neste momento, também pode utilizar o emulador de armazenamento do Azurite para executar e testar o código num ambiente local. Para obter mais informações, veja Utilizar o emulador do Azurite para o desenvolvimento local do Armazenamento do Azure.

Criar uma aplicação Java

Primeiro, verifique se o seu sistema de desenvolvimento cumpre os pré-requisitos listados na biblioteca de cliente do Armazenamento de Filas do Azure v12 para Java.

Para criar uma aplicação Java com o nome queues-how-to-v12:

  1. Numa janela da consola (como cmd, PowerShell ou Bash), utilize o Maven para criar uma nova aplicação de consola com o nome queues-how-to-v12. Escreva o seguinte mvn comando para criar um projeto Java "hello world".

     mvn archetype:generate \
         --define interactiveMode=n \
         --define groupId=com.queues.howto \
         --define artifactId=queues-howto-v12 \
         --define archetypeArtifactId=maven-archetype-quickstart \
         --define archetypeVersion=1.4
    
    mvn archetype:generate `
        --define interactiveMode=n `
        --define groupId=com.queues.howto `
        --define artifactId=queues-howto-v12 `
        --define archetypeArtifactId=maven-archetype-quickstart `
        --define archetypeVersion=1.4
    
  2. O resultado da geração do projeto deve ter um aspeto semelhante ao seguinte:

    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------< org.apache.maven:standalone-pom >-------------------
    [INFO] Building Maven Stub Project (No POM) 1
    [INFO] --------------------------------[ pom ]---------------------------------
    [INFO]
    [INFO] >>> maven-archetype-plugin:3.1.2:generate (default-cli) > generate-sources @ standalone-pom >>>
    [INFO]
    [INFO] <<< maven-archetype-plugin:3.1.2:generate (default-cli) < generate-sources @ standalone-pom <<<
    [INFO]
    [INFO]
    [INFO] --- maven-archetype-plugin:3.1.2:generate (default-cli) @ standalone-pom ---
    [INFO] Generating project in Batch mode
    [INFO] ----------------------------------------------------------------------------
    [INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
    [INFO] ----------------------------------------------------------------------------
    [INFO] Parameter: groupId, Value: com.queues.howto
    [INFO] Parameter: artifactId, Value: queues-howto-v12
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] Parameter: package, Value: com.queues.howto
    [INFO] Parameter: packageInPathFormat, Value: com/queues/howto
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] Parameter: package, Value: com.queues.howto
    [INFO] Parameter: groupId, Value: com.queues.howto
    [INFO] Parameter: artifactId, Value: queues-howto-v12
    [INFO] Project created from Archetype in dir: C:\queues\queues-howto-v12
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  6.775 s
    [INFO] Finished at: 2020-08-17T15:27:31-07:00
    [INFO] ------------------------------------------------------------------------
    
  3. Mude para o diretório criado queues-howto-v12 recentemente.

    cd queues-howto-v12
    

Instalar o pacote

Abra o pom.xml ficheiro no seu editor de texto. Adicione o seguinte elemento de dependência ao grupo de dependências.

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-storage-queue</artifactId>
  <version>12.6.0</version>
</dependency>

Configurar a aplicação para aceder ao Armazenamento de Filas

Adicione as seguintes instruções de importação à parte superior do ficheiro Java onde pretende utilizar as APIs de Armazenamento do Azure para aceder às filas:

// Include the following imports to use queue APIs
import com.azure.core.util.*;
import com.azure.storage.queue.*;
import com.azure.storage.queue.models.*;

Configurar uma cadeia de ligação do Armazenamento do Microsoft Azure

Um cliente do Armazenamento do Azure utiliza uma cadeia de ligação de armazenamento para aceder aos serviços de gestão de dados. Obtenha o nome e a chave de acesso principal da sua conta de armazenamento listadas no portal do Azure. Utilize-os como valores AccountName e AccountKey na cadeia de ligação. Este exemplo mostra como pode declarar um campo estático para conter a cadeia de ligação:

// Define the connection-string with your values
final String connectStr = 
    "DefaultEndpointsProtocol=https;" +
    "AccountName=your_storage_account;" +
    "AccountKey=your_storage_account_key";

Os exemplos seguintes partem do princípio de que tem um String objeto que contém a cadeia de ligação de armazenamento.

Como: Criar uma fila

Um QueueClient objeto contém as operações para interagir com uma fila. O código seguinte cria um QueueClient objeto. Utilize o QueueClient objeto para criar a fila que pretende utilizar.

public static String createQueue(String connectStr)
{
    try
    {
        // Create a unique name for the queue
        String queueName = "queue-" + java.util.UUID.randomUUID();

        System.out.println("Creating queue: " + queueName);

        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queue = new QueueClientBuilder()
                                .connectionString(connectStr)
                                .queueName(queueName)
                                .buildClient();

        // Create the queue
        queue.create();
        return queue.getQueueName();
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println("Error code: " + e.getErrorCode() + "Message: " + e.getMessage());
        return null;
    }
}

Como: Adicionar uma mensagem a uma fila

Para inserir uma mensagem numa fila existente, chame o sendMessage método . Uma mensagem pode ser uma cadeia (no formato UTF-8) ou uma matriz de bytes. Eis o código que envia uma mensagem de cadeia para a fila.

public static void addQueueMessage
    (String connectStr, String queueName, String messageText)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        System.out.println("Adding message to the queue: " + messageText);

        // Add a message to the queue
        queueClient.sendMessage(messageText);
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Como: Pré-visualizar a mensagem seguinte

Pode pré-visualizar a mensagem na frente de uma fila sem a remover da fila ao chamar peekMessage.

public static void peekQueueMessage
    (String connectStr, String queueName)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        // Peek at the first message
        PeekedMessageItem peekedMessageItem = queueClient.peekMessage();
        System.out.println("Peeked message: " + peekedMessageItem.getMessageText());
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Como: Alterar o conteúdo de uma mensagem em fila

Pode alterar os conteúdos de uma mensagem no local na fila de espera. Se a mensagem representar uma tarefa de trabalho, pode utilizar esta funcionalidade para atualizar o estado. O código seguinte atualiza uma mensagem de fila com novos conteúdos e define o tempo limite de visibilidade para prolongar mais 30 segundos. Prolongar o tempo limite de visibilidade dá ao cliente mais 30 segundos para continuar a trabalhar na mensagem. Também pode manter uma contagem de repetições. Se a mensagem for repetida mais do que n vezes, irá eliminá-la. Este cenário protege contra uma mensagem que aciona um erro de aplicação sempre que é processado.

O seguinte exemplo de código procura na fila de mensagens, localiza o conteúdo da primeira mensagem que corresponde a uma cadeia de pesquisa, modifica o conteúdo da mensagem e sai.

public static void updateQueueMessage
    (String connectStr, String queueName,
    String searchString, String updatedContents)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        // The maximum number of messages to retrieve is 32
        final int MAX_MESSAGES = 32;

        // Iterate through the queue messages
        for (QueueMessageItem message : queueClient.receiveMessages(MAX_MESSAGES))
        {
            // Check for a specific string
            if (message.getMessageText().equals(searchString))
            {
                // Update the message to be visible in 30 seconds
                queueClient.updateMessage(message.getMessageId(),
                                          message.getPopReceipt(),
                                          updatedContents,
                                          Duration.ofSeconds(30));
                System.out.println(
                    String.format("Found message: \'%s\' and updated it to \'%s\'",
                                    searchString,
                                    updatedContents)
                                  );
                break;
            }
        }
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

O seguinte exemplo de código atualiza apenas a primeira mensagem visível na fila.

public static void updateFirstQueueMessage
    (String connectStr, String queueName, String updatedContents)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        // Get the first queue message
        QueueMessageItem message = queueClient.receiveMessage();

        // Check for a specific string
        if (null != message)
        {
            // Update the message to be visible in 30 seconds
            UpdateMessageResult result = queueClient.updateMessage(message.getMessageId(),
                                                                   message.getPopReceipt(),
                                                                   updatedContents,
                                                                   Duration.ofSeconds(30));
            System.out.println("Updated the first message with the receipt: " +
                    result.getPopReceipt());
        }
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Como: Obter o comprimento da fila

Pode obter uma estimativa do número de mensagens numa fila.

O getProperties método devolve vários valores, incluindo o número de mensagens atualmente numa fila. A contagem só é aproximada porque as mensagens podem ser adicionadas ou removidas após o seu pedido. O getApproximateMessageCount método devolve o último valor obtido pela chamada para getProperties, sem chamar Armazenamento de Filas.

public static void getQueueLength(String connectStr, String queueName)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        QueueProperties properties = queueClient.getProperties();
        long messageCount = properties.getApproximateMessagesCount();

        System.out.println(String.format("Queue length: %d", messageCount));
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Como: Desativar a mensagem seguinte

O código descongestiona uma mensagem de uma fila em dois passos. Quando liga receiveMessagepara , recebe a mensagem seguinte numa fila. Uma mensagem devolvida receiveMessage torna-se invisível para qualquer outra mensagem de leitura de código desta fila. Por predefinição, esta mensagem permanece invisível durante 30 segundos. Para concluir a remoção da mensagem da fila, também tem de chamar deleteMessage. Se o código não conseguir processar uma mensagem, este processo de dois passos garante que pode obter a mesma mensagem e tentar novamente. O código chama deleteMessage logo após o processamento da mensagem.

public static void dequeueMessage(String connectStr, String queueName)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        // Get the first queue message
        QueueMessageItem message = queueClient.receiveMessage();

        // Check for a specific string
        if (null != message)
        {
            System.out.println("Dequeing message: " + message.getMessageText());

            // Delete the message
            queueClient.deleteMessage(message.getMessageId(), message.getPopReceipt());
        }
        else
        {
            System.out.println("No visible messages in queue");
        }
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Opções adicionais para descodificação de mensagens

Existem duas formas de personalizar a obtenção de mensagens a partir de uma fila. Primeiro, obtenha um lote de mensagens (até 32). Em segundo lugar, defina um tempo limite de invisibilidade mais longo ou mais curto, permitindo ao seu código mais ou menos tempo para processar totalmente cada mensagem.

O seguinte exemplo de código utiliza o receiveMessages método para obter 20 mensagens numa chamada. Em seguida, processa cada mensagem com um for ciclo. Também define o tempo limite de invisibilidade para cinco minutos (300 segundos) para cada mensagem. O tempo limite é iniciado para todas as mensagens ao mesmo tempo. Quando tiverem passado cinco minutos desde a chamada para o , as mensagens não eliminadas voltarão a receiveMessagesficar visíveis.

public static void dequeueMessages(String connectStr, String queueName)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        // The maximum number of messages to retrieve is 20
        final int MAX_MESSAGES = 20;

        // Retrieve 20 messages from the queue with a
        // visibility timeout of 300 seconds (5 minutes)
        for (QueueMessageItem message : queueClient.receiveMessages(MAX_MESSAGES,
                Duration.ofSeconds(300), Duration.ofSeconds(1), new Context("key1", "value1")))
        {
            // Do processing for all messages in less than 5 minutes,
            // deleting each message after processing.
            System.out.println("Dequeing message: " + message.getMessageText());
            queueClient.deleteMessage(message.getMessageId(), message.getPopReceipt());
        }
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Procedimentos: Listar as filas

Para obter uma lista das filas atuais, chame o QueueServiceClient.listQueues() método, que devolverá uma coleção de QueueItem objetos.

public static void listQueues(String connectStr)
{
    try
    {
        // Instantiate a QueueServiceClient which will be
        // used to list the queues
        QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
                                    .connectionString(connectStr)
                                    .buildClient();

        // Loop through the collection of queues.
        for (QueueItem queue : queueServiceClient.listQueues())
        {
            // Output each queue name.
            System.out.println(queue.getName());
        }
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Procedimentos: Eliminar uma fila

Para eliminar uma fila e todas as mensagens contidas na mesma, chame o delete método no QueueClient objeto.

public static void deleteMessageQueue(String connectStr, String queueName)
{
    try
    {
        // Instantiate a QueueClient which will be
        // used to create and manipulate the queue
        QueueClient queueClient = new QueueClientBuilder()
                                    .connectionString(connectStr)
                                    .queueName(queueName)
                                    .buildClient();

        System.out.println("Deleting queue: " + queueClient.getQueueName());

        // Delete the queue
        queueClient.delete();
    }
    catch (QueueStorageException e)
    {
        // Output the exception message and stack trace
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

Dica

Veja o repositório de amostras de código do Armazenamento do Azure

Para obter exemplos de código de Armazenamento do Azure ponto a ponto fáceis de utilizar que pode transferir e executar, veja a nossa lista de Exemplos de Armazenamento do Azure.

Passos seguintes

Agora que aprendeu as noções básicas do Armazenamento de Filas, siga estas ligações para saber mais sobre tarefas de armazenamento mais complexas.

Para exemplos de código relacionados com SDKs java preteridos versão 8, veja Code samples using Java version 8 (Exemplos de código que utilizam Java versão 8).