Partilhar via


Como usar o armazenamento em fila a partir do Java

Visão geral

Este guia mostrará como codificar para cenários comuns usando o serviço de Armazenamento de Filas do Azure. Os exemplos são escritos em Java e usam o SDK de Armazenamento do Azure para Java. Os cenários incluem inserir, espiar, obter e apagar mensagens da fila. O código para criar e excluir filas também é abordado. Para obter mais informações sobre filas, consulte a seção Próximas etapas .

O que é armazenamento em fila?

O Armazenamento de Filas do Azure é um serviço para armazenar um grande número de mensagens que podem ser acessadas de qualquer lugar do mundo por meio de chamadas autenticadas usando HTTP ou HTTPS. Uma única mensagem de fila pode ter até 64 KB de tamanho e uma fila pode conter milhões de mensagens, até o limite de capacidade total de uma conta de armazenamento. O armazenamento em fila é frequentemente usado para criar uma lista de pendências de trabalho para processar de forma assíncrona.

Conceitos do Serviço de Fila

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

Componentes do serviço de fila do Azure

  • Conta de armazenamento: Todo o acesso ao Armazenamento do Azure é feito através de uma conta de armazenamento. Para obter mais informações sobre contas de armazenamento, consulte Visã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 como nomear filas, consulte Nomeando filas e metadados.

  • Mensagem: Uma mensagem, em qualquer formato, de até 64 KB. O tempo máximo que uma mensagem pode permanecer na fila é 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 indicando que a mensagem não expira. Se esse parâmetro for omitido, o tempo de vida padrão será de sete dias.

  • Formato URL: As filas podem ser endereçadas usando o seguinte formato de URL: http://<storage account>.queue.core.windows.net/<queue>

    A seguinte URL aponta para uma fila no diagrama:

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

Criar uma conta de armazenamento do Azure

A maneira mais fácil de criar sua primeira conta de armazenamento do Azure é usando o portal do Azure. Para saber mais, consulte Criar uma conta de armazenamento.

Você também pode criar uma conta de armazenamento do Azure usando o Azure PowerShell, a CLI do Azure ou o Provedor de Recursos de Armazenamento do Azure para .NET.

Se preferir não criar uma conta de armazenamento no Azure neste momento, você também pode usar o emulador de armazenamento Azurite para executar e testar seu código em um ambiente local. Para obter mais informações, consulte Usar o emulador Azurite para o desenvolvimento local do Armazenamento do Azure.

Criar uma aplicação Java

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

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

  1. Em uma janela de console (como cmd, PowerShell ou Bash), use o Maven para criar um novo aplicativo de console com o nome queues-how-to-v12. Digite 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 ser parecido com isto:

    [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 recém-criado queues-howto-v12.

    cd queues-howto-v12
    

Instale o pacote

Abra o ficheiro pom.xml 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 seu aplicativo para acessar o Armazenamento em Fila

Adicione as seguintes instruções de importação à parte superior do arquivo Java onde você deseja usar as APIs de Armazenamento do Azure para acessar 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 conexão do Azure Storage

Um cliente de Armazenamento do Azure usa uma cadeia de conexão de armazenamento para acessar serviços de gerenciamento de dados. Obtenha o nome e a chave de acesso primária para sua conta de armazenamento listada no portal do Azure. Use-os como os valores AccountName e AccountKey na cadeia de conexã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 a seguir pressupõem que você tenha um String objeto que contém a cadeia de conexão de armazenamento.

Como: Criar uma fila

Um QueueClient objeto contém as operações para interagir com uma fila. O código a seguir cria um objeto QueueClient. Use o QueueClient objeto para criar a fila que você deseja usar.

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 em uma fila existente, chame o método sendMessage. Uma mensagem pode ser uma cadeia de caracteres (no formato UTF-8) ou uma matriz de bytes. Aqui está o código que envia uma mensagem de cadeia de caracteres 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 visualizar a próxima mensagem

Você pode visualizar a primeira mensagem de uma fila sem removê-la da fila chamando 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

Você pode alterar o conteúdo de uma mensagem diretamente na fila. Se a mensagem representar uma tarefa de trabalho, você poderá usar esse recurso para atualizar o status. O código a seguir atualiza uma mensagem de fila com novos conteúdos e define o tempo limite de visibilidade para estender mais 30 segundos. Estender o tempo limite de visibilidade dá ao cliente mais 30 segundos para continuar trabalhando na mensagem. Você também pode manter uma contagem de retentativas. Se a mensagem for repetida mais de n vezes, você a excluirá. Esse cenário protege contra uma mensagem que dispara um erro de aplicativo cada vez que ele é processado.

O exemplo de código a seguir pesquisa a fila de mensagens, localiza o conteúdo da primeira mensagem que corresponde a uma cadeia de caracteres 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 exemplo de código a seguir 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

Você pode obter uma estimativa do número de mensagens em uma fila.

O getProperties método retorna vários valores, incluindo o número de mensagens atualmente em uma fila. A contagem é apenas aproximada porque as mensagens podem ser adicionadas ou removidas após o seu pedido. O getApproximateMessageCount método retorna o último valor recuperado pela chamada para getProperties, sem chamar o 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 retirar a próxima mensagem da fila

Seu código retira uma mensagem da fila em duas etapas. Quando você liga para receiveMessage, você recebe a próxima mensagem em uma fila. Uma mensagem retornada de receiveMessage torna-se invisível para qualquer outro código que leia mensagens desta fila. Por padrão, essa mensagem permanece invisível por 30 segundos. Para concluir a remoção da mensagem da fila, você também deve chamar deleteMessage. Se o código não conseguir processar uma mensagem, esse processo de duas etapas garante que você possa receber a mesma mensagem e tentar novamente. O seu código chama deleteMessage imediatamente após a mensagem ter sido processada.

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 retirar mensagens da fila

Há duas maneiras de personalizar a recuperação de mensagens de uma fila. Primeiro, receba um lote de mensagens (até 32). Em segundo lugar, defina um tempo limite de invisibilidade maior ou menor, permitindo que seu código tenha mais ou menos tempo para processar completamente cada mensagem.

O exemplo de código a seguir usa o método receiveMessages para obter 20 mensagens em uma chamada. Em seguida, ele processa cada mensagem usando um for loop. Ele também define o tempo limite de invisibilidade para cinco minutos (300 segundos) para cada mensagem. O tempo limite inicia-se para todas as mensagens ao mesmo tempo. Quando passarem cinco minutos desde a chamada para receiveMessages, as mensagens não apagadas voltarão a ficar 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();
    }
}

Como listar as filas

Para obter uma lista das filas atuais, chame o QueueServiceClient.listQueues() método, que retornará 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();
    }
}

Como: Excluir uma fila

Para excluir uma fila e todas as mensagens contidas nela, chame o método delete no objeto QueueClient.

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

Sugestão

Confira o repositório de exemplos de código do Armazenamento do Azure

Para obter exemplos de código de Armazenamento do Azure de ponta a ponta fáceis de usar que você pode baixar e executar, confira nossa lista de Exemplos de Armazenamento do Azure.

Próximos passos

Agora que você aprendeu as noções básicas do armazenamento em fila, siga estes links para saber mais sobre tarefas de armazenamento mais complexas.

Para exemplos de código relacionados usando SDKs Java versão 8 preteridos, consulte Exemplos de código usando Java versão 8.