RabbitMQ & AMQP – #3 – Conceitos
Publicado em: quarta-feira, 20 de fev de 2019
Categorias: RabbitMQ de A a Z
Tags: AMQP | RabbitMQ

Agora é o momento de falarmos brevemente sobre cada elemento do AMQP. Nesse post ainda estamos tratando com superficialidade, mas é importantíssimo passar por aqui para progredirmos nessa jornada.

Standard vs Implementação

Standard que trata de mensageria. No AMQP não temos termos como Exchanges, Queues e Binds, vemos termos como Transport, Source e Target, portanto embora possamos olhar pela perspectiva do AMQP, tomei a liberdade de falar sobre a perspectiva de uma de suas implementações, no caso o RabbitMQ, já que é foco do nosso estudo. Mas vale muito a pena olhar o standard, os links estão logo a seguir.

AMQP é gerido pela OASIS que por sua vez cuida de dezenas de outros standards. O AMQP especificamente pode ser detalhado aqui e aqui.

O RabbitMQ é composto por poucos elementos, e exige certa criatividade para compor os diversos cenários de uso. Enfim não tem mágica nem jeitinho, você precisa de fato conhecer o fundamento. Assim vamos abordar Mensagens, entender que a função das exchanges é tão fundamental quanto entender o conceito de filas, e por isso, vou abordar exchange antes de abordar filas. Também falaremos de Virtual Host, Routing Keys e Binds, e sim, esse é o fim da explicação sobre RabbitMQ. RabbitMQ é composto somente por esses elementos.

RabbitMQ é um message broker, uma implementação AMQP, a mais usada do mercado. Com a dependência do Standard como AMQP, os problemas de impedância entre soluções de mensageria são minimizados e em alguns casos até eliminados.

Na mensageria existem papéis

Quando falamos de mensageria, devemos ficar atentos a quem exerce um papel e que papel é esse.

Ator

Vou chamar de ator qualquer parte do seu código, pode ser um serviço, um sistema inteiro, não importa muito, é alguém que realiza uma operação.

Producer

Um producer/publisher é um ator que publica uma mensagem no message broker.

Embora você possa ter o ímpeto de pensar “é quem publica uma mensagem em uma fila“, na prática vamos ver que há um intermediador, que é a exchange, e seu papel no fluxo invalida essa afirmação.

Portanto, vamos definir como alguém que está tentando publicar uma mensagem no message broker.

Consumer

Um consumer é um ator que consome mensagens de uma ou mais filas. É quem realiza o processamento de uma mensagem que está na fila.

Dissecando o RabbitMQ

Virtual Host

O virtual host é um ambiente isolado dentro de uma instância do RabbitMQ. Nele temos usuários e roles, e todos os objetos como filas, exchanges, e suas ligações, os binds. Cada virtual host é isolado dos demais. Por padrão, uma instalação do RabbitMQ vem com o Root, um virtual host como os demais, no entanto ele não possui um nome. Na uri AMQP ele é definido como amqp://user:pass@host:10000/, enquanto um virtual host AAA usaria uma uri assim amqp://user:pass@host:10000/AAA.

Na interface de gerenciamento escolhemos um virtual host por vez para gerenciar.

Mensagem

Uma mensagem é um objeto que tem o propósito de chegar a uma ou mais filas #spoiler para assim serem processada(s).

Uma mensagem AMQP consiste em um envelope, nesse envelope temos headers (semelhante aos headers http) e payload (o body efetivamente).

Os cabeçalhos são úteis para diversas finalidades, inclusive roteamento. Alguns tipos de exchange usam esses cabeçalhos em conjunto com os binds para decidir em qual ou quais filas uma mensagem deve ser enviada. Veremos isso ainda nesse post. Os cabeçalhos também são muito úteis e podem te ajudar a entender o tipo da mensagem (formato de encoding) etc.

Exchange

Exchange é um objeto programável de roteamento.

Isso quer dizer que você pode definir um conjunto de regras de roteamento. Essas regras podem fazer uma mensagem ir direto para uma fila, ou mesmo ser distribuída em diversas filas ou em outros casos ser descartada mesmo.

Há implementações de plugins para RabbitMQ em que você pode até escrever scripts de roteamento. Dê uma olhada no projeto script-exchange para entender.

Como funciona?

Um publisher, SEMPRE envia sempre uma mensagem para uma Exchange.

No RabbitMQ, não existe envio de mensagem direto para filas.

As mensagens SEMPRE passam por uma exchange.

#spoiler

A exchange pode ser de diversos tipos, e é na exchange que acontece a escolha da fila a ser enviada a mensagem (ou das filas…).

O RabbitMQ possui tipos de exchange, cada uma com um comportamento diferente.

A que você possivelmente mais vai estar habituado é a direct. A direct exerce o papel de Exchange Fake, pois ela não toma decisão alguma, ela não possui nome, faz um bypass para enviar a mensagem para a fila que possui o nome que você enviou. Em vez de enviar a mensagem para o nome da exchange, você usa o nome da fila, a exchange direct (que é padrão, mas pode ser excluída) fará você ter a impressão de que está enviando a mensagem para uma fila direto… mas lembre-se. Fisicamente isso não existe e a exchange direct pode ser removida por você.

Os tipos de Exchange são detalhados no link AMQP Concepts.

Exchanges predefinidas no RabbitMQ

NameDefault pre-declared names
Direct exchange(Empty string) and amq.direct
Fanout exchangeamq.fanout
Topic exchangeamq.topic
Headers exchangeamq.match (and amq.headers in RabbitMQ)

Filas

Pronto, enfim chegamos às filas, um dos elementos mais simples da estrutura do RabbitMQ. 

Filas são objetos internos do RabbitMQ que armazenam mensagens e gerenciam sua distribuição para os consumers. É delas que você consome mensagens. É o ponto central de qualquer arquitetura de mensageria. 

A forma de trabalho mais comum, depende de você entrar na administração do RabbitMQ, e criar filas com nomes específicos, configurações etc. Essas filas, geralmente criadas assim “possuem CPF”, isso quer dizer, seu nome representa algo relevante para você e para sua arquitetura. Elas são referenciadas, você armazena esses nomes em strings de configuração para poder enviar como parâmetro de roteamento.

Mas outro tipo de fila, MUITO MAIS COMUM DO QUE VOCÊ POSSA PENSAR, são as filas dinâmicas, criadas por um consumidor. 

Talvez, nesse momento você tenha se perguntado: Mas como? Como eu vou criar uma fila dinamicamente, onde cairiam as mensagens enquanto eu não criar a fila?

Antes de ser mais formal, entregando uma definição a respeito dos tipos de filas vou dar um exemplo:

Imagine um cluster com 10 máquinas, consequentemente 10 serviços, cada 1 em uma máquina. Imagine que eu preciso notificar cada uma das máquinas para que todas façam a mesma atividade. Lembre-se, como um cluster tolerante a falhas, as máquinas podem cair. No entanto vamos supor que minha mensagem só faça sentido para quando as máquinas estivessem online. Isso quer dizer que um nó fora do ar, não deve receber mensagem alguma. Como resolver isso?

A gente deve criar, manualmente uma exchange com um nome que faça sentido.

No ator que consumirá a mensagem da fila, devemos adicionar (em 1 ou 2 linhas de código) as chamadas para a criação de sua fila. Essa fila será:

Anônima: Não possui um nome predefinido, o RabbitMQ gera um nome dinamicamente e devolve no momento da criação.

Exclusiva: somente 1 consumidor poderá consumir mensagens dessa fila.

Auto-delete: Caso seu consumidor caia ou morra ou o cluster saia do ar, a fila precisa ser excluída, pois não faz sentido sua existência mais.

Por fim, na segunda linha criamos a associação entre a exchange e essa fila que acabamos de criar. O único cuidado, e você deve estar se perguntando sobre isso, é para usarmo so o tipo adequado de exchange para que possamos garantir que uma mensagem chegará a todas as filas.

Assim, temos 2 tipos de filas:

  • Nomeadas – Filas que possuem um nome pré-definido. Isso quer dizer que você previamente a cria, seja via API ou via Management Console. São filas que possuem “CPF”, o nome dela tem relevância para sua implantação. Essas em geral, são filas que nunca morrem, elas nascem e duram a vida toda.
  • Anônimas – São filas criadas dinamicamente por demanda. Esse tipo de fila é alicerce das implementações de RPC, por exemplo, é na fila anônima que recebemos o response. Isso acontece pois ao criar uma fila anônima, seu provider AMQP recebe no código o nome da fila, criado dinamicamente pelo RabbitMQ. Esse nome é útil para criar associações entre exchange e fila, por exemplo, ou para enviar no cabeçalho de uma mensagem, quando você está esperando uma resposta de uma requisição nessa fila.
  • Durável ou não durável: A fila persiste entre restarts do RabbitMQ?
  • Exclusive / Não exclusiva: Somente 1 consumidor poderá consumir a fila, e quando o consumidor cair a fila será deletada.

Com essas configurações, e um pouco de engenhosidade fazemos muitas coisas, usamos as abordagens mais diversas possíveis. Mas é preciso atenção. Muito cuidado com os detalhes, ter certeza de que está usando os tipos de recursos adequados.

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

class Send
{
    public static void Main()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using(var connection = factory.CreateConnection())
        using(var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "hello",
                                 durable: false,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            string message = "Hello World!";
            var body = Encoding.UTF8.GetBytes(message);

            channel.BasicPublish(exchange: "",
                                 routingKey: "hello",
                                 basicProperties: null,
                                 body: body);
            Console.WriteLine(" [x] Sent {0}", message);
        }

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

Tirado do próprio site do RabbitMQ, na linha 13 vemos a criação de uma fila:

  • Nomeada
  • Não durável
  • Não exclusiva
  • Sem Auto-delete

Na linha 22 vemos a publicação de uma mensagem

Pela ausência do nome da exchange, sabemos que esse ator espera que a exchange (direct) seja usada para enviar a mensagem para a fila que possui o mesmo nome da routing key

Bindings

Por fim o último conceito necessário para entender AMQP são os bindings, que consistem em associações entre exchange e filas. Nelas você pode ter informações de rotas entre outras coisas.

Os bindings, só fazem sentido em tipos específicos de exchanges. É no bind que definimos a routing key. Uma chave de rota que determina que o bind deve ser usado. 

 

Próximos passos

Com esse post, acabaram as definições a respeito do RabbitMQ, amanhã teremos um QnA (Perguntas e Respostas), com as dúvidas mais comuns de quem está vendo filas pela primeira vez.

Luiz Carlos Faria

Mensagem do Autor

Espero que goste desse post. Não deixe de comentar e falar o que achou. 

Se acha que esse post pode ajudar alguém que você conheça, compartilhe!

 

Eventos passados

agosto 2020
julho 2020
Nenhum evento encontrado!
Carregar Mais

Publicidade

Assine

0 comentários

Enviar um comentário

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

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.

Agenda & Eventos

agosto

setembro 2020

outubro
DOM
SEG
TER
QUA
QUI
SEX
SAB
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
Eventos para setembro

1st

Sem Eventos
Eventos para setembro

2nd

Sem Eventos
Eventos para setembro

3rd

Sem Eventos
Eventos para setembro

4th

Sem Eventos
Eventos para setembro

5th

Sem Eventos
Eventos para setembro

6th

Sem Eventos
Eventos para setembro

7th

Sem Eventos
Eventos para setembro

8th

Sem Eventos
Eventos para setembro

9th

Sem Eventos
Eventos para setembro

10th

Sem Eventos
Eventos para setembro

11th

Sem Eventos
Eventos para setembro

12th

Sem Eventos
Eventos para setembro

13th

Sem Eventos
Eventos para setembro

14th

Sem Eventos
Eventos para setembro

15th

Sem Eventos
Eventos para setembro

16th

Sem Eventos
Eventos para setembro

17th

Sem Eventos
Eventos para setembro

18th

Sem Eventos
Eventos para setembro

19th

Sem Eventos
Eventos para setembro

20th

Sem Eventos
Eventos para setembro

21st

Sem Eventos
Eventos para setembro

22nd

Sem Eventos
Eventos para setembro

23rd

Sem Eventos
Eventos para setembro

24th

Sem Eventos
Eventos para setembro

25th

Sem Eventos
Eventos para setembro

26th

Sem Eventos
Eventos para setembro

27th

Sem Eventos
Eventos para setembro

28th

Sem Eventos
Eventos para setembro

29th

Sem Eventos
Eventos para setembro

30th

Sem Eventos
Share This