Utilizando Filas no .NET com Azure Storage Queue

Marcio Nizzola
8 min readNov 17, 2023
Utilizando filas no .NET com Azure Storage Queue

Quando precisamos utilizar o conceito de filas no Azure, existe um serviço de Storage chamado “Azure Storage Queue” que permite a criação e utilização de filas para organização de mensagens.

Para quem nunca utilizou algum serviço similar, a proposta é de fato criar uma fila para realizar o processamento de dados, respeitando logicamente a ordem em que é inserida uma “mensagem”, no conceito FIFO, primeiro a entrar, primeiro a sair.

Este conceito é usado para facilitar a comunicação e o processamento de eventos em aplicativos e sistemas distribuídos.

Aqui estão alguns conceitos-chave sobre o trabalho com filas:

Fila: É uma estrutura de armazenamento na nuvem que mantém uma lista ordenada de mensagens. As mensagens são adicionadas à fila por um aplicativo produtor e processadas por um aplicativo consumidor.

Produtor: Um aplicativo ou serviço que envia mensagens para a fila.

Consumidor: Um aplicativo ou serviço que lê mensagens da fila e as processa.

Mensagem: Uma unidade de dados que contém informações específicas a serem transmitidas entre os componentes do aplicativo. As mensagens na fila são processadas em ordem FIFO (primeiro a entrar, primeiro a sair).

Tempo de Visibilidade: O tempo durante o qual uma mensagem fica invisível após ser lida por um consumidor. Isso evita que outras instâncias do consumidor a processem simultaneamente.

Azure Storage Queue

Modelo de utilização do Azure Storage Queue

Algumas características do serviço Azure Storage Queue:

  • Suporta mensagens de até 64 kb
  • Uma fila pode ter milhões de mensagens, até atingir o limite de armazenamento da conta no Azure.
  • Mensagens podem ser acessadas em qualquer lugar do mundo via Http ou Https
  • o nome das filas deve estar em letras minúsculas
  • mensagens tem uma duração padrão de 7 dias, mas pode ser configurado para não expirar também.
  • o preço é bastante baixo, sendo cobrado Us$ $0.045 por GB mensal.

Producer x Consumer

Para testar este conceito, vamos criar um projeto onde iremos publicar mensagens numa fila (producer), e outro projeto que irá consumir estas mensagens (consumer).

diagrama exemplificando o conceito de Producer e Consumer

Este é um modelo bastante utilizado no mercado, devido á sua flexibilidade, podendo haver vários Produtores que inserem itens nas filas, e vários consumidores, que em paralelo dão vazão às mensagens inseridas, permitindo assim atender à demandas altas com escalabilidade.

Criando o serviço no Azure

Para podermos testar o nosso software temos que criar um serviço Azure Storage Queue na nuvem Azure:

1 — faça o login no Portal Azure

2- Crie um serviço de Storage

Após criar o serviço, acesse-o e configure as filas, para isso na página do serviço storage, role para ver as opções mais abaixo

Clique daí no link “Fila” conforme a figura:

3- Crie a fila

Ao acessar as filas no serviço de Storage, você não terá inicialmente nenhuma fila, mas no botão “+ Fila” você poderá criar quantas filas quiser, como estou fazendo na figura.

Depois de Criada, a fila aparecerá conforme a figura abaixo:

4 — Obtenha as credenciais de acesso

Acesse a tela de Chaves de acesso conforme demonstrado na figura abaixo:

De posse dos dados monte a sua connection string para colocar no appsettings.json da aplicação, a connection string será igual à string abaixo, onde você deverá trocar o nome do seu storage e a chave obtidos na página anterior.

“DefaultEndpointsProtocol=https;AccountName=nomedostorage;AccountKey=sua chave;EndpointSuffix=core.windows.net”

Vamos ao código

Para utilizar o serviço de Storage do Azure, teremos que adicionar uma biblioteca nuget:

Azure.Storage.Queues

Como eu não gosto de replicar códigos, vou aproveitar e criar um projeto de uma biblioteca onde poderei até depois gerar um pacote Nuget para utilizar em outras aplicações.

Projeto 1: Biblioteca Azure Queue

Para isto, no Visual Studio, selecione o tipo de projeto conforme a figura:

Darei o nome “Nizzola.AzureQueue.Toolkit” dado que será a biblioteca que conterá as ferramentas para acessar o Azure Queue.

Criado o projeto, vamos adicionar 3 itens nele que serão:

INizzolaAzureQueueService = uma interface com a assinatura dos métodos que utilizaremos para manipular as filas.

Serão criados apenas 3 métodos:

1- DequeueMessageAsync será responsável por obter uma mensagem da fila.

2 — EnqueueMessageAsync será responsável pela publicação de uma mensagem na fila

3- CountMessages informa o número de mensagens na fila.

Segue o código:

namespace Nizzola.AzureQueue.Toolkit
{
public interface INizzolaAzureQueueService
{
Task<string?> DequeueMessageAsync();
Task EnqueueMessageAsync(string messageContent);
Task<int?> CountMessages();
}
}

Criaremos uma classe: NizzolaAzureQueueService = onde implementaremos os métodos definidos na interface.

Aqui está o coração da aplicação, portanto irei expor com mais detalhes como funciona método a método.

1- Construtor da classe: nele receberemos via injeção de dependência um objeto “NizzolaAzureQueueOptions” que contém a string de conexão com a fila do Azure, e iremos instanciar o objeto “_client” com a configuração recebida.

2-EnqueueMessageAsync: Neste método será inserida uma mensagem na fila, seu processo é bastante simples e basta dois métodos importantes (linha 23 e 26).

O primeiro cuida para que seja criada uma fila no serviço caso ela não exista, já o segundo faz a escrita da mensagem na fila, neste caso considerei a mensagem como um string.

3-DequeueMessageAsysnc: Neste método será obtida uma mensagem da fila.

Neste método há alguns passos a mais:

Primeiramente criamos um objeto do tipo “QueueProperties” linha 39, para obter as propriedades da fila, para que no If subsequente possamos validar se há mensagens para ser extraídas, através do método “AproximateMessagesCount”.

Depois na linha 43, é obtida uma mensagem da fila com o comando “ReceiveMessagesAsync”.

Na linha 45, verificamos se há conteúdo na mensagem, com a propriedade “Lenght”, caso isso seja verdadeiro, removemos a mensagem na linha 48, e depois retornamos a mensagem na linha 50.

4-CountMessages:

Como o próprio nome já diz, o método faz a contagem das mensagens utilizando os comandos da linha 66 e retornando na linha 68.

Classe NizzolaAzureQueueOptions = classe para armazenar as configurações do serviço, que serão obtidas na inicialização da aplicação.

namespace Nizzola.AzureQueue.Toolkit
{
public class NizzolaAzureQueueOptions
{
public string QueueName { get; set; }
public string ConnectionString { get; set; }
}
}

Feito o projeto responsável pelo acesso as filas, agora será necessário criar mais 3 projetos, pois quero deixar melhor organizada a estrutura do projeto (se quiser saber mais, veja meu post “por que organiza-se software em vários projetos?”)

Projeto 2- Criação do domínio

Aqui será um projeto do tipo “ClassLibrary” onde irei colocar apenas uma classe, que utilizaremos como base para a nossa comunicação, simulando um sistema de pagamentos.

namespace AzureQueue.Domain;

public class PaymentModel
{
public int Id { get; set; }
public string? Description { get; set; }
public decimal Value { get; set; }
public string? PaymentType { get; set; }
}

Projeto 3 — Producer

Neste projeto as coisas começam a acontecer, este será o projeto que irá realizar a escrita na fila, inserindo mensagens, iremos utilizar a nossa biblioteca do projeto “ToolKit” e referenciar também o projeto “Domain”.

Logo no Program.cs teremos toda a lógica da aplicação, para mostrar como é simples inserir mensagens na fila, uma vez que toda a programação está nas bibliotecas !

Nosso projeto é bastante simples e consiste em um arquivo “appsettings.json” que possui as credenciais para acesso ao Storage Azure.

E o próprio Program.cs.

Um detalhe importante, é que após criar o projeto, temos que configurar as referências externas para que ele tenha acesso aos itens dos demais projetos. Veja que ao clicar com o botão direito sobre “Dependencies” no projeto e escolher “Project References” veremos esta janela que permite fazer referências à outros projetos.

O arquivo appsettings.json possui estrutura simples onde devemos inserir apenas a chave do storage, que você pode obter direto no serviço azure.

{
"AzureQueue": {
"ConnectionString": "ponha sua chave aqui",
"QueueName": "compras1"
}
}

Ao executá-lo, o loop irá publicar várias mensagens na fila

Veja como ficou após a execução no Azure:

Aí estão as mensagens publicadas !!

Projeto 4 — Consumer

Neste projeto, teremos a implementação de fato de quem irá fazer a leitura de uma fila, para começar, vamos criar um projeto como um “Worker Service” (para quem não sabe veja este link), e para obter os elementos que deverão ser processados, iremos utilizar a nossa biblioteca do projeto “ToolKit” e referenciar também o projeto “Domain”.

No projeto teremos o “program.cs” onde está estruturado desta forma:

Mas todo o processo acontece na classe ‘Worker”, quando utilizamos worker services, a classe Worker possui uma estrutura pronta, onde o método “ExecuteAsync” é disparado para que nele seja executado o processo.

No seu formato padrão, o “Worker” é executado com um loop (linha 20) e dentro dele é que iremos implementar o código da leitura dos objetos da fila.

No construtor da classe, recebemos “INizzolaAzureQueueService” que é o serviço criado na biblioteca previamente, iremos consumí-lo para a partir dele realizar a leitura dos elementos da fila.

Na linha 23, é feita a leitura de um elemento, que será devolvido como uma string, que caso não seja nula, será deserializado no formato de objeto que estamos esperando “PaymentModel” (linha 28), e assim poderíamos depois fazer o que quiséssemos com ele, inserir em banco de dados, ou realizar outras operações.

Como é um projeto de cunho demonstrativo, somente estamos exibindo em tela para demonstrar que o processo funcionou:

Veja que a cada execução do Worker, ele foi até a fila e buscou uma mensagem, exibindo-a como esperado.

Então é só isso? sim, enviamos a mensagem, obtivemos de volta com o consumer !

Pronto, temos um Producer e Consumer funcionais !

Gostou do artigo? clique no ícone👏e me siga para ver as próximas publicações !! Quer ver mais conteúdos, acesse minhas redes através do Linktree: https://linktree.com/nizzola

Referência:

--

--

Marcio Nizzola

Microsoft MVP | Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.