RabbitMQ — Primeiros passos (repost de 2018)
Rafael Honório

Rafael Honório @rafahs

About: Senior Software Engineer, currently I'm working with Elixir and Golang.

Location:
Brazil
Joined:
Aug 8, 2021

RabbitMQ — Primeiros passos (repost de 2018)

Publish Date: May 20
0 0

How does it work?

Hey oh!

Olá! Quero compartilhar um pouco da minha experiência com o RabbitMQ nos últimos meses. A ideia é criar uma espécie de guia introdutório para quem está começando.

Como a maior parte do conteúdo (inclusive a documentação) está em inglês, resolvi escrever este mini artigo/tutorial para a galera da comunidade que, assim como eu, está melhorando no inglês.

Se você chegou até aqui, provavelmente já sabe o que é um message broker. Mas caso tenha caído de paraquedas, dá uma olhada nesse artigo da Wikipédia e usa o bom e velho Google Tradutor, ele ajuda bastante!

Entre as opções de mercado como Kafka, ActiveMQ, SQS, entre outros, o RabbitMQ é uma excelente escolha. E o melhor: é open source, ao contrário de algumas alternativas citadas. No geral, é uma ferramenta bem completa.

O RabbitMQ tem suporte oficial para várias linguagens: C#, Java, PHP, Python, Ruby, Go, Elixir e por aí vai, as mais utilizadas atualmente.

Neste artigo, divido o conteúdo em três partes:

  • Cenários de aplicação
  • Conceitos
  • Mão na massa

Cenários de aplicação

Gosto de resumir o uso do RabbitMQ em dois cenários comuns:

  • Quando uma aplicação distribuída precisa se comunicar com várias outras (fanout).
  • Quando você precisa executar um processo de forma assíncrona, por exemplo: é bem comum em e-commerce dentro do processo de compra, ter várias etapas para finalizar uma compra, carrinho, pagamento, processamento, envio e por ai vai...(topic)
Image description
cenário bem comum

A maioria dos casos de uso vai acabar derivando dessas duas situações.


Conceitos

Aqui vão alguns conceitos importantes do RabbitMQ. (Não se preocupe se parecer muita coisa, eu também me perdi nos primeiros dias lendo a documentação.)

A forma mais básica de usar um message broker é: um app envia uma informação para outro app.

app-to-app
Cenário mais simples

Produtor envia uma informação para uma fila (queue) e um consumidor pega essa informação, conceito simples, não é mesmo?

app-to-app-detail
Um pouco mais detalhado

Claro que existem alguns poréns no processo, mas vamos direto ao ponto. Aqui vão os principais conceitos:

  • Queue: É a fila dentro do servidor RabbitMQ. As filas têm propriedades como exchange, binds, headers e content, que explico a seguir.

  • Exchange: É o “roteador” das mensagens. Ele decide como e para onde as mensagens serão enviadas. Existem quatro tipos: Direct, Fanout, Topic e Headers.

  • Bind ou RoutingKey: É o identificador que conecta uma queue a uma exchange. Ele define o caminho que a mensagem vai seguir.

message broker

  • Producer / Publisher: A aplicação que produz e envia a mensagem para o RabbitMQ.

  • Consumer / Subscriber: A aplicação que consome a mensagem da fila.

  • Virtual host: O RabbitMQ é multi-tenant, ou seja, permite múltiplos ambientes lógicos. Cada vhost separa conexões, filas, binds, exchanges, policies e usuários. Se você já trabalhou com virtual hosts no Apache ou blocos de servidores no Nginx, a ideia é parecida, mas no RabbitMQ, esses hosts são criados via rabbitmqctl ou pela API.

Com esses conceitos em mente, fica muito mais fácil entender o restante. Tentei manter o texto leve e informal pra facilitar :D


Mão na massa

Agora vamos configurar o servidor e começar a codar!

Vou usar um servidor Linux (Debian) e a linguagem C#, mas o conceito se aplica a qualquer linguagem com suporte a RabbitMQ.


Passo 1 – Instalar o Erlang

Execute os seguintes comandos:

wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get update
sudo apt-get install erlang erlang-nox
Enter fullscreen mode Exit fullscreen mode

Passo 2 – Instalar o RabbitMQ Server

sudo add-apt-repository 'deb http://www.rabbitmq.com/debian/ testing main'
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get install rabbitmq-server
Enter fullscreen mode Exit fullscreen mode

Inicie e habilite o serviço:

sudo systemctl enable rabbitmq-server
sudo systemctl start rabbitmq-server
Enter fullscreen mode Exit fullscreen mode

Pare o servidor (temporariamente):

sudo systemctl stop rabbitmq-server
Enter fullscreen mode Exit fullscreen mode

Criar usuário para o Web Management

sudo rabbitmqctl add_user admin password 
sudo rabbitmqctl set_user_tags admin administrator
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
Enter fullscreen mode Exit fullscreen mode

Habilite o plugin de administração:

sudo rabbitmq-plugins enable rabbitmq_management
Enter fullscreen mode Exit fullscreen mode

Inicie o servido novamente:

sudo systemctl start rabbitmq-server
Enter fullscreen mode Exit fullscreen mode

Acesse o painel web em http://localhost:15672
(Usuário: admin / Senha: password)

Image description

Liberar portas no firewall (se necessário)

sudo firewall-cmd --add-port=15672/tcp --permanent
sudo firewall-cmd --add-port=5672/tcp --permanent
sudo firewall-cmd --add-port={4369/tcp,25672/tcp} --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Enter fullscreen mode Exit fullscreen mode

Desta forma o servidor já está configurado, vou mostrar um exemplo criando uma fila e enviando uma informação e consumir em outra app. Existem várias abordagens para trabalhar com rabbitmq, criando uma API http, cronjob, background job e por ai vai.


Passo 3 – Criar uma aplicação para interagir com o RabbitMQ*

Crie uma Console App e adicione a dependência do RabbitMQ client.

dotnet add package RabbitMQ.Client
Enter fullscreen mode Exit fullscreen mode

ou

Image description

Crie uma classe para envio de mensagens:

Image description

using RabbitMQ.Client;
using System;
using System.Text;

namespace NewTask
{
    class NewTask
    {
        static void Main(string[] args)
        {
            ConnectionFactory factory = new ConnectionFactory()
            {
                HostName = "localhost",
                Port = Protocols.DefaultProtocol.DefaultPort,
                UserName = "admin",
                Password = "admin",
                VirtualHost = "/",
                RequestedHeartbeat = 60
            };

            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.ExchangeDeclare(
                        exchange: "MediumExchange",
                        type: ExchangeType.Topic,
                        autoDelete: false
                    );

                    channel.QueueDeclare(
                        queue: "queueMediumTeste",
                        durable: true,
                        exclusive: false,
                        autoDelete: false,
                        arguments: null
                    );

                    channel.QueueBind(
                        queue: "queueMediumTeste",
                        exchange: "MediumExchange",
                        routingKey: "MediumBind"
                    );

                    var message = "Olá Medium";
                    var body = Encoding.UTF8.GetBytes(message);

                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;

                    channel.BasicPublish(
                        exchange: "MediumExchange",
                        routingKey: "MediumBind",
                        basicProperties: properties,
                        body: body
                    );

                    Console.WriteLine(" [x] Sent {0}", message);
                }
            }

            Console.WriteLine("Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Esse código realiza os seguintes passos:

  • Cria uma Exchange
  • Cria uma Queue
  • Cria um Bind
  • Envia a mensagem (convertida em bytes)
  • Define se ela deve ser persistida
  • Publica a mensagem
  • Mostra no console
Image description
a mensagem enviada para o servidor

Agora, crie outro arquivo para consumir a mensagem da fila:

Image description

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;

namespace ConsumerPublishSub
{
    class Program
    {
        static void Main(string[] args)
        {
            ConnectionFactory factory = new ConnectionFactory()
            {
                HostName = "localhost",
                Port = Protocols.DefaultProtocol.DefaultPort,
                UserName = "admin",
                Password = "admin",
                VirtualHost = "/",
                RequestedHeartbeat = 60
            };

            using (IConnection connection = factory.CreateConnection())
            {
                using (IModel channel = connection.CreateModel())
                {
                    Console.WriteLine("Waiting for logs.");

                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body;
                        var message = Encoding.UTF8.GetString(body.ToArray());
                        Console.WriteLine(" [x] Received {0}", message);
                    };

                    channel.BasicConsume(
                        queue: "QueueMediumTeste",
                        autoAck: true,
                        consumer: consumer
                    );

                    Console.WriteLine(" Press [enter] to exit.");
                    Console.ReadLine();

                    channel.Close();
                }

                connection.Close();
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

A mensagem esperada será:

Image description
o resultado esperado

Esse é o básico para começar a usar RabbitMQ com .NET.
No site oficial há um Get Started completo para várias linguagens.

No futuro, quero escrever sobre clusters com RabbitMQ, estou criando uma lib para facilitar essas interações, e em breve compartilho aqui.

Curtiu? Me chama!
Se tiver dúvidas ou quiser trocar ideia:

OBS: esse texto foi escrito em 2018, transferi o artigo para o dev.to por que o medium ficou uma merda, valeu!

Comments 0 total

    Add comment