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
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
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.
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).
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:
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:
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
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.,
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.
Oi Tiago, não tenho não mas qual seria a dificuldade que você esta encontrando.
Quem sabe não posso te ajudar?
Abs.,
Rafael, acho que era por causa da rede da empresa. Pois eu fiz o teste em casa e consegui reproduzir.
Ahh show de bola
Abs.,