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:
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
:
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 seguintemvn
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
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] ------------------------------------------------------------------------
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 receiveMessage
para , 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 receiveMessages
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();
}
}
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.
- Azure Storage SDK for Java (SDK do Armazenamento do Azure para Java)
- Referência do SDK do cliente do Armazenamento do Azure
- API REST dos Serviços de Armazenamento do Azure
- Blogue da equipa do Armazenamento do Azure
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).