Criando canal de mensagens com RabbitMQ e Node.js

Olá pessoal! Hoje irei mostrar como criar um canal de mensagens usando RabbitMQ e Node.js. Primeiramente, você deve tê-los instalado na sua máquina. Você pode realizar o download do RabbitMQ em: https://www.rabbitmq.com/download.html e do NodeJS em: https://nodejs.org/pt-br/download/.

Vamos começar?

Primeiramente, temos que ter em mente o conceito de fila. Caso não conheça a estrutura de dado fila, dê uma olhada neste artigo: https://www.mundojs.com.br/2019/11/01/estrutura-de-dados-com-javascript-fila/ para podermos dar sequência à este artigo.

No RabbitMQ, temos um produtor de mensagens (P) e um consumidor (C). As mensagens ficam armazenadas dentro de uma fila. No diagrama abaixo, a caixa do meio é a fila. O produtor de mensagens envia uma mensagem para a fila, e o consumidor a recebe:

Enviando:

Crie um arquivo send.js, que será o arquivo do produtor de mensagens. No nosso send.js, precisamos realizar a requisição da biblioteca amqplib. Isso pode ser feito desta maneira:

let amqp = require('amqplib/callback_api');

Em seguida, conectaremos ao servidor RabbitMQ:

amqp.connect('amqp://localhost', function(error0, connection) {
    if (error0)throw error0;
});

Agora, criaremos um canal onde reside a API para a realização das tarefas, onde devemos declarar uma fila para o envio, e também publicar uma mensagem na fila:

amqp.connect('amqp://localhost', function(error0, connection) {
    if (error0) throw error0;
    connection.createChannel(function(error1, channel) {
        if (error1) throw error1;
        
        let queue = 'hello';
        let msg = 'Olá Mundo!';

        channel.assertQueue(queue, {
            durable: false
        });
        channel.sendToQueue(queue, Buffer.from(msg));

        console.log(" [x] Enviando %s", msg);
    });
});

Agora, precisamos fechar a conexão e sair:

setTimeout(function() {
    connection.close();
    process.exit(0);
}, 500);

E o nosso código do produtor de mensagens seria mais ou menos assim:

let amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function(error0, connection) {
    if (error0) {
        throw error0;
    }
    connection.createChannel(function(error1, channel) {
        if (error1) throw error1;
        
        let queue = 'hello';
        let msg = 'Olá Mundo!';

        channel.assertQueue(queue, {
            durable: false
        });
        channel.sendToQueue(queue, Buffer.from(msg));

        console.log(" [x] Enviando %s", msg);
    });
    setTimeout(function() {
        connection.close();
        process.exit(0);
    }, 500);
});

Recebendo:

Agora, nosso consumidor precisa escutar as mensagens enviadas pelo arquivo send.js. O consumidor precisa ficar ativo para escutar as mensagens enviadas. Crie um arquivo chamado receive.js. Este arquivo terá a configuração parecida com o do arquivo send.js. Abrimos uma conexão, um canal e declaramos a fila que iremos consumir:

let amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function (error0, connection) {
    if (error0) throw error0;
    connection.createChannel(function (error1, channel) {
        if (error1) throw error1;
        let queue = 'hello';
        channel.assertQueue(queue, {
            durable: false
        });
     });
});

Queremos garantir a existência de uma fila para que o consumidor não fique iniciando antes do emissor. É exatamente isso que o channel.consume faz:

console.log(' [*] Esperando por mensagens em %s. Para sair pressione CTRL+C', queue);
channel.consume(queue, function (msg) {
    console.log(' [x] Recebida: %s', msg.content.toString());
    }, {
        noAck: true
    });

E o nosso código do consumidor ficaria assim:

let amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function (error0, connection) {
    if (error0) throw error0;
    connection.createChannel(function (error1, channel) {
        if (error1) throw error1;
        let queue = 'hello';
        channel.assertQueue(queue, {
            durable: false
        });
        console.log(' [*] Esperando por mensagens em %s. Para sair pressione CTRL+C', queue);
        channel.consume(queue, function (msg) {
            console.log(' [x] Recebida: %s', msg.content.toString());
        }, {
            noAck: true
        });
    });
});

Executando:

Agora, executando no terminal cada um dos arquivos, temos as seguintes saídas:

Produtor de mensagens:

Consumidor:

E assim está feito o nosso canal de emissão de mensagens!

Gostou deste artigo? Comente abaixo!