O Azure Service Bus é um sistema de mensagem como serviço (MaaS) que proporciona o desacoplamento de aplicações por meio da distribuição de mensagens entre sistemas. Esse desacoplamento permite a criação de soluções altamente escalonáveis.
Mas antes da implementação, iremos entender como o serviço funciona e os conceitos envolvidos.
Conceitos
O que é uma mensagem?
Uma mensagem é um tipo de dados que serve para a comunicação entre os sistemas. Essa mensagem pode ser um simples JSON como também um arquivo de imagem ou apenas texto. Uma mensagem é dividida em Payload e em Label.
- Payload: O payload é o corpo da mensagem onde estão localizados os dados que serão transmitidos.
- Label: O label serve para informar quem receberá a mensagem.
O que é uma fila?
A fila é o local onde as mensagens ficam armazenadas após serem enviadas pelo remetente e também é o local onde o receptor irá receber mensagens para então processá-las.
O que são os tópicos?
Os tópicos também são utilizados para enviar e receber mensagens. Enquanto a fila é usado apenas para comunicação ponta-a-ponta, os tópicos são utilizados para cenários onde hajam múltiplos receptores. Um receptor inscrito em um tópico recebe uma cópia de cada mensagem presente naquele tópico.
Demonstração
Com esses conceitos em mente, estaremos prontos para iniciar um pequeno projeto simulando o clássico produtor/consumidor. Para esse exemplo iremos utilizar as seguintes ferramentas:
Para os universitários de plantão: o Azure disponibiliza um crédito de U$100,00 para você utilizar os serviços sem precisar cadastrar um cartão de crédito. Ative seu benefício aqui!
Criando o Service Bus no Azure
O processo de criação do recurso Service Bus é muito simples. É necessário realizar o login e acessar o painel do Azure. Você pode criar o recurso através do menu localizado a esquerda ou pesquisando por Service Bus na barra de pesquisa, como mostrado abaixo:
Durante a criação do recurso, serão solicitadas algumas informações. Preencha semelhante a imagem abaixo, clique em Create e aguarde a finalização do processo de criação.
Após finalizado o processo de criação, devemos salvar a string de conexão gerada. É através dessa string que nossa aplicação se comunicará com o Azure e enviará/receberá as mensagens. Para isso, entre no recurso Service Bus criado e através do menu de navegação esquerdo, em Settings, procure por Shared access policies.
Clique em RootManageSharedAccessKey
Em seguida, anote a string de conexão mostrada em Primary Connection String
Certo, agora precisamos criar uma fila para armazenar as mensagens em nosso Service Bus. Para isso, vá até Overview e clique em Queue. Será exibido um formulário para configurarmos nossa fila. Veja a imagem abaixo como exemplo e após preenchido clique em Create.
Após finalizado, estaremos prontos para desenvolver nossa aplicação de exemplo.
Mão na massa
Abra seu Visual Studio Code e no terminal crie um novo projeto Node.js através do comando:
npm init -y
Esse comando irá criar um arquivo package.json padrão. Abra o package.json e substitua pelo código abaixo:
{
"name": "azure-service-bus",
"version": "1.0.0",
"description": "Exemplo de funcionamento do Azure Service Bus",
"main": "src/factory.js",
"scripts": {
"factory": "node src/factory.js",
"consumer": "node src/consumer.js"
},
"repository": {
"type": "git",
"url": "https://github.com/jrafaelsantana/azure-servicebus-exemplo.git"
},
"author": "Rafael Santana",
"license": "MIT"
}
Organizando o projeto
Crie os diretórios e arquivos conforme a imagem abaixo:
Instalando as dependências
Para esse exemplo precisamos instalar dois pacotes. São eles:
- @azure/service-bus
- config
O @azure/service-bus é uma biblioteca para criar clientes do Azure Service Bus em Node.js. Para instalar, execute o comando:
npm install @azure/service-bus
O config é um pacote para definirmos parâmetros de ambiente. Usaremos esse pacote para manter nosso código organizado e limpo. Instale o config através do comando:
npm install config
Configurações da conexão
Abra o arquivo config/default.json e preencha seguindo o modelo abaixo:
{
"Azure": {
"serviceBus": {
"queueName": "NOME DE SUA FILA",
"connectionString": "SUA STRING DE CONEXÃO"
}
}
}
Todas nossas variáveis de ambiente serão armazenadas nesse arquivo, facilitando a manutenção do código.
Criação do produtor de mensagens
Abra o arquivo src/factory.js e inclua o código abaixo. O código está com comentários explicando trechos importantes.
const config = require('config');
const { ServiceBusClient } = require("@azure/service-bus");
async function main() {
//Cria a conexão com o Service Bus utilizando as configurações em config/default.json
const cliente = ServiceBusClient.createFromConnectionString(config.get('Azure.serviceBus.connectionString'));
const fila = cliente.createQueueClient(config.get('Azure.serviceBus.queueName'));
const sender = fila.createSender();
try {
//Fabricamos 20 mensagens
for (let i = 0; i < 20; i++) {
//Esse será o conteúdo das nossas mensagens
const message = {
body: 'Mensagem ' + i,
label: 'testes',
properties: {
country: 'Brazil',
state: 'PE'
}
};
await sender.send(message); //Envia mensagem
console.log('Enviou a mensagem ' + i)
}
await fila.close(); //Finaliza o cliente da fila
} finally {
await cliente.close(); //Finaliza o cliente do Service Bus
}
}
main().catch((err) => {
console.log(err);
});
Criação do consumidor de mensagens
Abra o arquivo src/consumer.js e insira o código abaixo. Semelhante ao factory.js, o código está com comentários explicando seu funcionamento.
const config = require('config');
const { ServiceBusClient, ReceiveMode } = require("@azure/service-bus");
async function main() {
//Cria a conexão com o Service Bus utilizando as configurações em config/default.json
const cliente = ServiceBusClient.createFromConnectionString(config.get('Azure.serviceBus.connectionString'));
const fila = cliente.createQueueClient(config.get('Azure.serviceBus.queueName'));
const receiver = fila.createReceiver(ReceiveMode.ReceiveAndDelete); //Cria um receptor no modo ReceiveAndDelete
try {
//Cria um loop que aguarda novas mensagens serem inseridas na fila para consumi-las
for await (let message of receiver.getMessageIterator()) {
if (typeof message != 'undefined') {
console.log('Mensagem recebida: ' + message.body);
await message.complete(); //Informa que a mensagem foi lida
}
}
await fila.close(); //Finaliza o cliente da fila
} finally {
await cliente.close(); //Finaliza o cliente do Service Bus
}
}
main().catch((err) => {
console.log("Error occurred: ", err);
});
Pronto, nosso produtor e consumidor já estão concluídos. Vamos executar nosso projeto de exemplo para verificar se está funcionando corretamente. Primeiramente, vamos testar nosso factory.js. Para isso, vá até o terminal e execute o comando:
npm run factory
Se for mostrado algo semelhante a imagem acima, o seu factory.js está funcionando. Agora, vamos testar nosso consumer.js utilizando o comando:
npm run consumer
Tudo certo! As mensagens foram consumidas da nossa fila. Note que nosso consumer.js continua em execução mesmo após ter consumido todas as mensagens da fila. Isso acontece pois nosso consumidor foi construído para sempre verificar a existência de novas mensagens. Experimente executar novamente o consumer.js enquanto o factory.js está aguardando as mensagens.
Você também pode receber um conjunto de mensagem de uma única vez utilizando o método receiveMessages como o exemplo abaixo:
//Consume um conjunto de 10 mensagens de uma única vez
const messages = await receiver.receiveMessages(10);
console.log(messages.length + ' mensagens recebidas:');
for await (let message of messages) {
console.log(message.body);
await message.complete();
}
Conclusão
Interessante, não é? O Azure Service Bus é uma ferramenta indispensável para sua aplicação se tornar altamente escalável. A biblioteca do Service Bus não está disponível apenas para o Node.js mas também para .NET, Java, Python, PHP e Ruby.
Se quiser saber mais sobre as funcionalidades do Azure Service Bus visite a documentação oficial. A documentação é bastante completa e contém vários exemplos de código.
Todo o código está disponibilizado nesse repositório.
Até a próxima!
=D
Top comments (0)