Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Microsserviços na prática: mensageria com RabbitMQ

Microsserviços na prática: mensageria com RabbitMQ

Requisições assíncronas - Apresentação

Boas-vindas ao Curso de Microsserviços na prática: mensageria com RabbitMQ da Alura! Meu nome é Jacqueline Oliveira e serei a sua instrutora ao longo desse treinamento direcionado à arquitetura de microsserviço.

Neste curso continuaremos o nosso projeto do Alura Food, que desenvolvemos em Java e Spring. No treinamento anterior, trabalhamos com comunicação síncrona com o Spring Cloud OpenFeign.

Neste curso, vamos entender melhor as desvantagens desse tipo de comunicação e como o RabbitMQ, um dos Message broker mais usados no mercado atualmente, pode nos ajudar com o desafio de fazer a comunicação entre os sistemas distribuídos, que podem estar em linguagens diferentes ou tecnologia.

Nosso objetivo é que esses sistemas se comuniquem independente da linguagem e tecnologia usada no seu desenvolvimento. Com isso, entenderemos em detalhes os principais conceitos de enfileiramento de mensagens, como manipular as queues (em português, "fileiras") do RabbitMQ.

Além disso, vamos trabalhar com a exchange (em português, "intercâmbio"), são as formas de roteamento: como a mensagem será enviada, para quem, quais são os consumidores dessa mensagem.

Faremos, na prática, uma aplicação que envia mensagem e outras aplicações que as consomem. Vamos entender como lidar com falhas e como manter uma alta disponibilidade da aplicação, para não ocorrer perda de mensagem quando uma das instâncias estiver fora do ar.

Para você aproveitar bem o curso, é necessário já ter concluído os treinamentos anteriores, em que trabalhamos com a arquitetura de microsserviços e aprendemos os conceitos necessários. É fundamental conhecer o Docker, porque vamos executar o RabbitMQ a partir de um Container Docker.

Te espero no próximo vídeo, para iniciarmos os nossos estudos.

Vamos lá?

Requisições assíncronas - Por que utilizar mensageria

Nesta aula, vamos entrar na parte teórica do que é necessário que você já possua algum conhecimento prévio para iniciarmos o projeto.

Ao longo dos cursos de microsserviços, um dos maiores desafios que enfrentamos ao trabalhar com sistemas distribuídos é a comunicação entre eles. No momento de fazer a arquitetura, precisamos entender qual a melhor estratégia para realizar essa comunicação.

Comunicação Síncrona x Assíncrona

Na comunicação síncrona fazemos uma analogia à conversa telefônica. Ao realizar uma pergunta ao telefone, aguardamos um retorno imediato. Isto é, ficamos parado e esperando esse retorno para ter uma ação.

Já a comunicação assíncrona pode ser associada a uma conversa por WhatsApp, em que enviamos uma mensagem e aguardamos o retorno, e vamos fazer outras coisas durante essa espera. Isto é, esperamos a resposta para analisar se vamos ter uma ação ou não.

Qual estratégia de comunicação entre microsserviços aplicamos no Alura Food?

No primeiro curso, o projeto no Alura Food tinha dois microsserviços:

  1. Pagamentos-ms
  2. Pedidos-ms

Cada vez que um pagamento era confirmado, uma mensagem era enviada para o microsserviço de pedidos avisando estar pago e que podia seguir com a solicitação. Porém, ficávamos esperando a confirmação do pagamento do pedido, ou seja, era uma comunicação síncrona.

Inclusive, projetamos um circuit breaker, um sistema de fallback caso o pedido não confirmasse que recebeu o pagamento. A partir disso, usamos o Spring Cloud OpenFeign do Spring Cloud, que em pagamentos tínhamos uma interface chamada PedidoClient, em que representávamos qual o tipo de requisição feita para o microsserviço de pedidos.

No service, chamávamos o client na hora de confirmar o pagamento e o enviava para tentar fazer a requisição informando que o pedido estava pago. Isto é, uma comunicação síncrona usando o OpenFeign, em que criamos o FeignClient indicando qual era o microsserviço.

Porém, essa forma gerava alguns problemas. Por mais que atendesse ao que estávamos precisando, quando o microsserviço de pedidos estava fora do ar ou quando não retornasse se recebeu, pegávamos o pagamento já confirmado e lançávamos um status "Confirmado sem integração".

pagamento.get().serStatus(Status.CONFIRMADO_SEM_INTEGRACAO);

Transferência de responsabilidade

Nesse processo, estamos transferindo uma responsabilidade que não é do serviço de pagamentos, porque o pagamento já estava confirmado. Não deveríamos colocar esse status de confirmado sem integração e, depois, fazer uma nova tentativa de integração. Isso é uma transferência de responsabilidade, neste caso, estamos passando para o serviço de pagamentos uma tarefa que não é dele.

Serviços se comunicando diretamente

Outro problema são os serviços se comunicando diretamente.

@FeignClient("pedidos-ms")

No serviço de pagamentos declaramos de forma direta que estávamos nos comunicando com o microsserviço chamado pedido-ms, isto é, tinha um acoplamento. Porém, se em algum momento resolvermos alterar essa arquitetura? Ou que é o microsserviço de administração que vai receber a confirmação do pagamento e enviar para o pedido?

Para fazer essas alterações, seria necessário ir ao serviço de pagamentos e mudar, porque acoplamos - colocamos para se comunicar diretamente. A comunicação síncrona atendia ao que precisávamos, até mesmo porque o pagamento deveria ser confirmado para seguir com o pedido.

Uma maneira de resolver esse problema, é usando uma ferramenta para fazer essa comunicação de forma síncrona e eficiente. Como? Inserindo uma camada intermediária entre os serviços de pagamentos e pedidos.

Logo, o serviço de pagamentos desenvolvido com Spring envia uma mensagem para outro serviço que redireciona a mensagem para o serviço de pedidos. Este vai processar e continuar com o fluxo.

A ferramenta responsável por essa camada intermediária é o RabbitMQ. Podemos associar ao exemplo do WhatsApp: ao enviar uma mensagem para alguém, ela vai para o servidor e o WhatsApp analisa para qual telefone deve ser enviado e redireciona a mensagem para a pessoa.

No nosso caso será a mesma coisa, o serviço de pagamentos vai remeter uma mensagem para o RabbitMQ, e este vai distribuir para a aplicação de destino. Com isso, não temos mais sistemas se comunicando de forma direta e não temos dependência, o pagamento foi confirmado e enviada uma mensagem para a fila sem precisar ficar aguardando um retorno.

Podemos, inclusive, usar aplicações em tecnologias distintas. Ou seja, nem todas precisam estar no Spring, por exemplo. Isso porque não está ocorrendo uma comunicação direta.

Portanto, o RabbitMQ nos fornece essa liberdade de atuar com diversas tecnologias e linguagens.

Nesta aula tivemos um breve resumo do que são os conceitos de comunicação síncrona e assíncrona e tivemos uma noção de como o RabbitMQ vai nos auxiliar ao longo do projeto.

No próximo vídeo, vamos conhecer o RabbitMQ.

Te espero lá!

Requisições assíncronas - Conhecendo o RabbitMQ

Nesta aula, vamos aprender algumas características do RabbitMQ.

Message broker

A função de um message broker (em português, "Agente de mensagens") é atuar como intermediário na gestão do envio e recebimento das mensagens.

Open source

Por ser open source (em português, "Código aberto"), é uma ferramenta que a comunidade contribui por ser fácil de modificar.

Suporte e plugins para várias linguagens

Geralmente, o RabbitMQ trabalha em duas frentes quando nos referimos às características cliente e servidor. Este último é o administrador do RabbitMQ, desenvolvido em Erlang e os clients são as bibliotecas que implementam essa interface de publicar ou consumir mensagens na linguagem que estivermos desenvolvendo a aplicação.

Documentação oficial RabbitMQ

Protocolo AMQP

O RabbitMQ oferece suporte para diversos protocolos, como MQTT (Message Queuing Telemetry Transport), STOMP e HTTP. Mas o principal protocolo dele é o AMQP (Advanced Message Queuing Protocol, em português "Protocolo de enfileiramento de mensagens avançado").

A AMQP é um protocolo avançado de enfileiramento de mensagens, baseado no TCP (Transmission Control Protocol). Por isso, é rápido e confiável.

O RabbitMQ usa o padrão Pub/Sub (Publish/Subscribe). Com isso, teremos um publicador que divulga a mensagem e um consumidor, o subscribe, que consome essa mensagem.

O subscribe pode ser associado a um assinante, ele vai assinar que receberá mensagens de uma determinada fila. Para exemplificar, é como em um grupo do WhatsApp, em que a mensagem enviada é recebida por todos que estão no grupo.

Como funciona a publicação de mensagens?

Para isso, trabalhamos com o Queue, sendo a fila. Isto é, como as mensagens são armazenadas. Essas filas possuem diversas características que vamos aprendendo ao longo do curso, mas, por exemplo, podem ser duráveis, armazenadas em banco de dados, entre outros aspectos. Há também as propriedades, como o tamanho máximo de mensagens que podemos ter na fila e se ultrapassar esse tamanho qual a ação tomada.

Essa fila, segue uma característica chama FIFO (First In, First Out). Ou seja, a primeira mensagem que entra na fila será a primeira a ser entregue. Podemos configurar prioridades, mas esse é o padrão.

Exchanges

Geralmente, ao publicarmos uma mensagem não a jogamos direto na fila e sim criamos uma exchange - chamamos de "troca". Esta é responsável por capturar a mensagem que o publicador publicou, analisar, processar, descobrir para qual fila deve direcionar e enviar. A exchange está entre o publicador e as filas.

Há várias categorias de exchanges:

Default

Este tipo é um padrão que já vem com o broker, ao implementarmos não precisamos especificar qual a exchange, somente informamos o nome da fila. Por exemplo: enviar uma mensagem para a fila de pagamentos confirmados, e do outro lado há uma fila esperando essa mensagem de pagamentos confirmados.

Perceba que não estamos enviando diretamente para a fila e sim jogando para o RabbitMQ. A partir disso, ele transforma essa mensagem em um exchange padrão e direciona para a fila.

Portanto, na exchange default não indicamos o nome da exchange, somente indicamos a fila. Nenhuma mensagem é enviada diretamente para a fila.

Direct

Outro tipo de exchange é a direct, ou seja, direta. Ela envia a mensagem para uma fila específica, em que temos uma routing key (chave de roteamento) configurada e todas as filas que possuírem essa chave receberam essa mensagem.

Ele possui um algoritmo padrão chamado round-robin e os consumidores recebem as mensagens de forma balanceada. Isto é, se tivermos cinco consumidores para aquele tipo de exchange, a cada envio um deles irá receber.

Fanout

Esse tipo ignora a routing key, ele envia a mensagem para todos que possuem um vínculo com a fila, usando o binding key (em português, "chave de ligação"). Isto é, envia a mensagem para todas as filas relacionadas a determinada exchange.

Topic

É uma forma mais avançada de exchange, em que conseguimos determinar regras e configurar como será a entrega.

Header

Por fim, temos a Header Exchange, a menos usada. Esse tipo envia a mensagem baseada no cabeçalho, neste passamos qual a fila para ser direcionada.

Esses são os conceitos iniciais que precisamos saber para configurar e trabalhar com essa mensageria.

Te espero no próximo vídeo para configurarmos o ambiente.

Vamos lá?

Sobre o curso Microsserviços na prática: mensageria com RabbitMQ

O curso Microsserviços na prática: mensageria com RabbitMQ possui 173 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas