

Junior Alves
Senior Developer
Foto: Unsplash
Atualizado: 23 de junho de 2025 às 08:16
Leitura: 5 minutos de leitura
Criado: 23 de junho de 2025
Message Broker: O guia definitivo
Uma introdução com exemplos práticos em Node.js
Introdução
Como você pode perceber, recentemente iniciei uma série de posts sobre Arquitetura de Software, System Design, Observabilidade e outros tópicos.Inclusive, vamos ter muuuito conteúdo sobre esses assuntos por aqui.
E se você ainda não viu os posts anteriores, confere lá, vão te ajudar a iniciar seus estudos nessa etapa na sua carreira.
O cenário
Vamos começar imaginar essa cena: um cliente clica em "Finalizar Compra" no seu e-commerce. Nos bastidores, uma sequência de tarefas é disparada: o serviço de Pagamentos é acionado, depois o de Estoque para dar baixa no produto, em seguida o de Notificações para enviar o e-mail de confirmação e por fim, o de Logística.
Tudo parece lógico e coeso. Mas e se o serviço de e-mails estiver fora do ar? O sistema inteiro trava? A compra do cliente é cancelada por causa de um simples e-mail de confirmação?
Se você disser que "sim", ou que você não sabe do que estou falando, esse artigo é para você.
O acoplamento
Esse efeito dominó acontece quando as partes de um sistema estão tão intimamente conectadas que a falha em uma derruba todas as outras.
Elas estão dependentes e frágeis.
Acoplamento é o nível interdependência entre módulos ou serviços. É basicamente op grau de 'intimidade' que existe entre dois ou mais serviços.
Uma solução simples, mas poderosa
E se, em vez de um serviço 'telefonar' diretamente para o outro, ele simplesmente deixasse uma mensagem em um "quadro de aviso" central e seguisse com sua vida?
Os outros serviços poderiam pegar essa mensagem quando estiverem prontos. É exatamente essa mágica que um Message Broker faz.
O Message Broker
Um Message Broker atua como um serviço do correios (mas que funciona hehe) para a aplicação. Um serviço (o Producer
) não precisa saber onde o outro serviço (o Consumer
) mora. Ele apenas escreve uma carta (a Message
), e a entrega na agência de correios (o Broker
). Mais tarde, o destinatário vai até a sua caixa postal (Queue
) e retira a carta para ler quando puder.
Producer (Remetente): O serviço que origina a mensagem. (Ex: Serviço de Pedidos)
Consumer (Destinatário): O serviço que recebe e processa a mensagem. (Ex: Serviço de Notificações)
Message (A carta): O pacote de dados enviado. (Ex:{ "orderId": 123, "client": "client@email.com", "status": "confirmed" }
). Queue / Topic (A caixa postal ou quadro de aviso): O local dentro do Broker onde a mensagem fica armazenada temporariamente.
Filas VS Tópicos
Filas (Queues) — Comunicação Ponto-a-Ponto:
Analogia: Uma Fila (Queue) funciona como uma caixa de correio pessoal. Uma mensagem é entregue à fila e apenas um Consumer pode pegá-la. Depois que a mensagem é lida, ela desaparece. É o modelo perfeito para tarefas que devem ser executadas uma única vez, como 'enviar o e-mail de confirmação do pedido 456'.
Tópicos (Topics) — Padrão Publish/Subscribe:
Analogia: Um Tópico (Topic) é como um quadro de avisos público. O Producer 'prega' um aviso no quadro (Ex: 'O pedido 456 foi enviado!'). Vários Consumers interessados nesse tipo de aviso (Logística, Análise de Dados, Notificações) podem, cada um, ler uma cópia da mensagem e tomar suas próprias ações, sem que um interfira no outro.
Mão na massa
Para este exemplo, vamos usar Node.js e RabbitMQ.
A maneira mais fácil de rodar o RabbitMQ localmente é com Docker:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
producer.js
// Este script se conecta ao RabbitMQ, garante que uma fila chamada 'pedidos' exista, e envia uma mensagem para ela.
const amqp = require('amqplib');
async function sendOrder() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const queue = 'pedidos';
const msg = JSON.stringify({ pedidoId: 123, cliente: 'joao@email.com' });
await channel.assertQueue(queue, { durable: true }); // Garante que a fila exista e sobreviva a reinicializações
channel.sendToQueue(queue, Buffer.from(msg));
console.log(" [x] Pedido enviado: '%s'", msg);
setTimeout(() => {
connection.close();
process.exit(0);
}, 500);
}
sendOrder();
consumer.js
// Este script se conecta ao RabbitMQ e fica 'escutando' a fila 'pedidos'.
// Quando uma mensagem chega, ele a processa.
const amqp = require('amqplib');
async function processOrder() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const queue = 'pedidos';
await channel.assertQueue(queue, { durable: true });
console.log(" [*] Aguardando por pedidos na fila '%s'. Pressione CTRL+C para sair.", queue);
channel.consume(queue, (msg) => {
if (msg !== null) {
console.log(" [✔] Pedido recebido:", msg.content.toString());
// Aqui entraria a lógica de negócio (ex: enviar um e-mail, atualizar o estoque)
channel.ack(msg); // Confirma que a mensagem foi processada com sucesso
}
});
}
processOrder();
Pratique para fixar 🎉
Conclusão
Adotar Message Brokers não é apenas sobre usar uma nova tecnologia, não é sobre hype, é sobre evoluir como arquiteto de software. Suas aplicações se tornam:
- Mais Resilientes: O sistema continua funcionando mesmo que um serviço falhe.
- Mais Escaláveis: Se o processamento de e-mails está lento, basta adicionar mais Consumers de e-mail, sem tocar em mais nada.
- Mais Flexíveis: A comunicação indireta permite que você troque, atualize ou adicione novos serviços sem quebrar o que já existe.
E você? Já usou um Message Broker em algum projeto? Qual foi sua maior dificuldade? Compartilhe sua experiência nos comentários!
Obrigado por ler até aqui, grande abraço e até o próximo post!
Curtiu? Compartilhe esse post: