Primeiros Passos com RabbitMQ
Tags: rabbitmq, messaging, springboot
Published: 2020-12-08 11:39:34


**RabbitMQ** é um dos mais populares *message brokers* de código fonte aberto disponíveis no mercado. Fornece um mecanismo para comunicação assíncrona entre processos. Permite que mensagens, enviadas por um produtor (*producer*), sejam recebidas e armazenadas numa fila para que possam ser consumidas por um receptor (*consumer*).

Este artigo apresenta uma maneira simples e rápida (**sem reinventar a roda!** e com menos código possível) para criar uma fila, enviar e consumir mensagens do RabbitMQ, utilizando-se de componentes disponíveis no Spring Boot. 

&nbsp;
### **Rodando o RabbitMQ**
Para rodar localmente pode-se optar por instalar na sua máquina ou rodar direto de um container. No site ([RabbitMQ/download] (encurtador.com.br/bdvDP)) é possível escolher algumas opções de instalações para diferentes sistemas operacionais, ou até mesmo para rodar direto da *cloud*.

Outra opção é rodar através de uma imagem *Docker*, a qual utilizei para este artigo: 
`docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management`

O RabbitMQ possui uma UI de administração, que deve ser instalada separadamente, muito útil para avaliar o estado das filas, número de mensagens, conexões ou até mesmo para apagar a fila e/ou suas mensagens. A imagem Docker acima já vem com o *RabbitMQ Management* disponível e pode ser acessada através da URL http://localhost:15672, utilizando usuário e senha padrões **guest**/**guest**.

&nbsp;
### **Spring Boot**
Para darmos os primeiros passos com RabbitMQ, vamos iniciar criando um projeto SpringBoot com *Spring initializr*: https://start.spring.io/ (tudo inicia aqui!!)

Selecionar as dependências: Spring Web e Spring for RabbitMQ.

Após fazer o download do projeto, descompactar e abrir na sua IDE de preferência. Para este demo utilizei *IntelliJ Community edition* e *OpenJDK* 11.

**Código fonte:** https://github.com/efoscarini/rabbitmq-getting-started

&nbsp;
### **O Projeto**
Neste primeiro momento, vamos focar num projeto simples de *producer* e *consumer*.  Uma visão geral do projeto pode ser apresentada da seguinte forma:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/53kqjzgolaac7620dt6h.PNG)
> Esquema gerado via RabbitMQ simulator (http://tryrabbitmq.com/).

Producer envia uma mensagem para a *exchange*, com a *binding-key* “queue-a-key”, que por sua vez é encaminhada para a ”queue-a”, a qual o consumer vai estar conectado, e por fim receberá a mensagem enviada.  

&nbsp;
#### **Estrutura básica**
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sqwu9ba2kk50ez1l3nf3.PNG)
Pacotes:
* Config: Configuração da *Queue* e *Exchange*.
* Producer: *Controller* expondo um serviço REST para enviar uma mensagem para fila.
* Consumer: *Listener* para ler da fila.

&nbsp;
#### **Conexão do Spring Boot com o RabbitMQ**
No arquivo **application.yml** adicionamos *host* e *port* do servidor do RabbitMQ. A *configuração padrão* é **localhost** para o *host* e **5672** como a porta. Para este projeto, alterei somente o host para apontar para a minha **Docker machine**.

> Quando se utiliza a **configuração padrão**, não é necessário declarar esses atributos abaixo, nem mesmo *username* e *password*. 
> Lembrando que isto é possível por causa da extensão "Spring for RabbitMQ"

```
spring:
  rabbitmq:
    host: 192.168.99.102
    port: 5672
    username: guest
    password: guest
```
&nbsp;
#### **Configuração da Queue e Exchange:** 
Utilizando a anotação @Configuration do Spring, vamos criar dois arquivos de configuração. O arquivo QueueConfig contém a definição da nossa *Queue* (“queue-a”) enquanto o ExchangeConfig declara a *exchange*, *routing key* e o *binding* apontando para nossa fila de testes.

{% gist https://gist.github.com/efoscarini/4a26f7e123f4a6d9cba4d2c7c285038f %}

{% gist https://gist.github.com/efoscarini/4a20cc49e02fc4ef139b504b1b7b162b %}


&nbsp;
#### **Enviando mensagens para fila:**
Vamos expor um serviço REST (método POST), na classe *SendMessageController*, para o envio da mensagem para fila. Este serviço requer uma String como parâmetro, que será o conteúdo da mensagem.

A mensagem recebida por parâmetro será enviada para a "queue-a" através do **RabbitTemplate**. Observa-se que os parâmetros para envio são o nome da *exchange* e *routing key*, e não o nome da fila. Pois a *exchange* será responsável por enviar para fila correta conforme a rota "queue-a-key" informada.
{% gist https://gist.github.com/efoscarini/d400c71995212b712346b2bec8dff063 %}

&nbsp;
#### **Recebendo mensagens da fila:**
O código do *consumer*, QueueListener, é o mais simples de todos, pois para ler as mensagens da fila basta anotar o método com **@RabbitListener** e declará-lo com um parâmetro String que será o conteúdo da mensagem.
{% gist https://gist.github.com/efoscarini/55338ffadb5ced5d484d59704f199fd4 %}

&nbsp;
### **Como funciona tudo isso?**
* A *queue/exchange* declarados nos *beans* de configuração (/config) são automaticamente criadas pelo Spring no momento em que a aplicação se conecta com o RabbitMQ. Neste projeto, isso ocorre no momento em que o "RabbitListner" tenta ler uma mensagem da fila pela primeira vez. Sendo assim, essas configurações são utilizadas uma única vez em seu ambiente local, contudo, quando vamos implantar em outro ambiente não precisamos nos preocupar com a criação das filas.

* Nota-se que este projeto não requer qualquer configuração adicional para conexão com o RabbitMQ, apenas a propriedades do arquivo *application.yml*. No artigo de configurações avançadas vou abordar alguns parâmetros que podem ser definidos via aplicação para melhorar a performance. 

&nbsp;
### **Validando a aplicação**
* Iniciar o projeto Spring Boot.
Log de inicialização conectando no RabbitMQ:
```
INFO 2532 --- [nio-8080-exec-1] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#3f1a4795:0/SimpleConnection@5deb4b [delegate=amqp://guest@192.168.99.102:5672/, localPort= 50321]
```

* Enviar uma mensagem via REST. 
Exemplo: mensagem sendo enviada para fila (Insomnia REST client):
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/07se3mwycvk4qsuax2ds.PNG)

* Mensagem recebida e conteúdo apresentado nos logs
```
Message received from queue-a: "mensagem enviada para RMQ"
```
&nbsp;
### **Próximos capítulos:**
1. Trabalhando com objetos complexos (trafegando JSON) e explorando as propriedades da mensagem
2. Fanout e Topic exchanges
3. Configuração de filas de erro (*Dead Letter Queue*) e reprocessamento
4. Configurações avançadas

### **Referências:**
- https://www.rabbitmq.com/getstarted.html
- https://start.spring.io/
- https://github.com/efoscarini/rabbitmq-getting-started