Message Broker com RabbitMQ

9 ago

Fala Galera,

Hoje venho falar sobre como podemos desacoplar nossa aplicação, distribuindo o processamento de alguns serviços e ganhando escalabilidade. Esse paradigma em computação é conhecida como Computação Distribuída. Um dos conceito da computação distribuída é a troca de mensagem com a utilização de Filas. E neste post estarei demonstrando como usar uma topologia de fila com o RabbitMQ

O que é RabbitMQ Message Broker?

RabbitMQ é uma serviço de Message Broker, open source multiplataforma que foi desenvolvido em ERLANG, totalmente suportados por diversas linguagens de programação, fácil de usar, confiável, com administração nativa e failover.

Instalação

Para essa demostração, irei utilizar o Linux Ubuntu 14.04 LTS, nele estará instalado toda infraestrutura necessária

Vamos usar o APT-GET Repository para instalar o RabbitMQ, execute os comandos abaixos no terminal

Adicionar a entrada do RabbitMQ no source do ATP-GET

echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list

Adicionar a chave pública

wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -

Atualizar os pacotes

sudo apt-get update

Instalar o Message Broker

sudo apt-get install rabbitmq-server

 

Habilitando o Painel de Administração

Vamos habilita o seu painel de Administração assim ficará fácil de administrar os usuários, ver as filas e quantas mensagem cada fila tem.

Execute o comando abaixo para habilitar o Painel de Administração

rabbitmq-plugins enable rabbitmq_management

Com o comando executar, o painel de administração ficar acessível através da seguinte URL http://<servername>:15672. Para acessar o RabbitMQ cria um usuário para com o username guest e senha guest abaixo a imagem da página inicial do painel administrativo

rabbitmq

Dica: O usuário “guest” somente tem acesso ao painel de administração localmente caso esteja usando uma maquina virtual, crie um novo usuário através da aba Admin

Topologias

O RabbitMQ suporta diversas topologias que podemos usar para escalonar nosso processamos vou enumerar algumas suportadas

Topologia Simples – Consiste e um publisher e um consumer. Neste cenário o publisher envia uma mensagem para fila e o consumer recebe a mensagem da fila e realiza o processamento

simple

 

Topologia Worker- Consiste e um publisher e em um ou mais consumer. Neste cenário o publisher envia uma mensagem para fila e o RabbitMQ envia para o consumer que estiver disponível assim podemos escalar e colocar quantos consumer forem necessário. para realizar o processamento das mensagens. A fila do RabbitMQ é atômica ou seja, apenas um item da fila é obtido por vez, não há riscos de mais de um consumer obter a mesma mensagem.

worker

Publish/Subscriber: Consiste em fazer copia da mesma mensagem para uma ou mais filas que assinam esta mensagem e que contém um ou mais consumer. Para a copia de mensagem utilizaremos um fila chamada Exchange (fanout). 

publish

Aplicação de Exemplo em C#

Com o entendimento das topologias, vamos criar uma aplicação de exemplo que irá publicar uma mensagem na fila através do publisher e consumir esta mensagem através de um consumer

Vamos criar dois Console Applications, um será o responsável por enviar a mensagem para a fila e outra será o responsável por ler a mensagem da fila

Para utilizar os recursos da fila devemos instalar o pacote do RabbitMQ.Client através do NuGet Package. Execute o comando Install-Package RabbitMQ.Client  no Package Manager Console no Visual Studio

Publisher:

namespace Publisher
{
    class Program
    {
        static void Main(string[] args)
        {
            string hostName = "192.168.8.194";
            string userName = "sys";
            string password = "123456";
            string queueName = "Message-Queue";

            //Cria a conexão com o RabbitMq
            var factory = new ConnectionFactory()
            {
                HostName = hostName,
                UserName = userName,
                Password = password,
            };

            //Cria a conexão
            IConnection connection = factory.CreateConnection();

            //cria a canal de comunicação com a rabbit mq
            IModel channel = connection.CreateModel();

            //Cria a fila caso não exista
            channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);

            for (int i = 1; i <= 500; i++)
            {
                String mensagem = $"Enviando a mensagem {i}";
                byte[] body = Encoding.Default.GetBytes(mensagem);

                //Seta a mensagem como persistente
                IBasicProperties properties = channel.CreateBasicProperties();
                properties.Persistent = true;

                //Envia a mensagem para fila
                channel.BasicPublish(exchange: String.Empty, routingKey: queueName, basicProperties: properties, body:body);
            }

            Console.WriteLine("Mensagem enviadas para fila");
            Console.Read();            
        }
    }
}

Ao executar o programa do publisher ele envia as mensagem para a fila conforme a imagem abaixo:

rabbitmq2

Consumer:

namespace Consumer
{
    class Program
    {
        static void Main(string[] args)
        {
            string hostName = "192.168.8.194";
            string userName = "sys";
            string password = "123456";
            string queueName = "Message-Queue";

            const int NUMBER_OF_WORKROLES = 3;

            //Cria a conexão com o RabbitMq
            var factory = new ConnectionFactory()
            {
                HostName = hostName,
                UserName = userName,
                Password = password,
            };

            //Cria a conexão
            IConnection connection = factory.CreateConnection();

            //cria a canal de comunicação com a rabbit mq
            IModel channel = connection.CreateModel();

            for (int i = 0; i < NUMBER_OF_WORKROLES; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    lock (channel)
                    {

                        var consumer = new EventingBasicConsumer(channel);
                        consumer.ConsumerTag = Guid.NewGuid().ToString(); // Tag de identificação do consumidor no RabbitMQ
                        consumer.Received += (sender, ea) =>
                        {
                            var body = ea.Body;
                            var brokerMessage = Encoding.Default.GetString(ea.Body);

                            Console.WriteLine($"Mensagem recebida com o valor: {brokerMessage}");
                            
                            //Diz ao RabbitMQ que a mensagem foi lida com sucesso pelo consumidor
                            channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: true);
                        };

                        //Registra os consumidor no RabbitMQ
                        channel.BasicConsume(queueName, noAck: false, consumer: consumer);

                    }
                });
            }

            Console.Read();
        }
    }
}

Ao executar o programa consumer conseguiremos ler as mensagens da fila conforme figura abaixo:

rabbitmq3

O RabbitMQ é um produto muito poderoso e flexível. Neste post vimos algumas características de funcionamento porém existem outras características que o torna ele uma produto fantástico. Com o RabbitMQ podemos desacoplar fluxos de programação garantindo assim escalabilidade e performance. 

Para saber mais sobre o RabbitMQ clique aqui

O código deste post pode ser encontrado no meu GitHub através deste link

Abs e até a próxima

6 Replies to “Message Broker com RabbitMQ

  1. Bacana Rafael! Venho estudando comunicação entre bounded context e arquitetura de sistemas distribuídos nos últimos tempos e escolhi o rabbitmq como message broker.
    Acho bem importante nós, que fazemos parte da comunidade, falarmos um pouco mais como pegamos esses modelos e colocamos eles em pratica.
    Esse seu post é, sem duvida, bem útil e importante.

    • Oi Gustavo,
      Muito obrigado pela visita.
      Sim concordo, acho que indo além podemos estender esse tipo de desacoplamento para uma arquitetura reativa baseado em eventos e com o RabbitMQ permite esse tipo de aventuras já que ele suporta chamadas RPC.
      Abs.,

  2. Boa tarde Rafael, você teria um tutorial da instalação do rabbitmq pro windows. Pois acompanhando a documentação no site do mesmo não estou conseguindo.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *