O RabbitMQ é um message broker que propicia facilidade, onde implantar cenários avançados de roteamento, balanceamento de carga ou filas de mensagens persistentes são feitos em poucas linhas de código.
Por padrão o RabbitMQ utiliza o protocolo AMQP 0-9-1 para transição das suas mensagens, mas também tem suporte a outros protocolos como: STOMP, MQTT, AMQP 1.0 e HTTP, porém, segundo a documentação é recomendado a utilização do Rabbit com o protocolo padrão (AMQP 0-9-1), que é um protocolo binário com uma semântica de mensagens bastante forte.
A criação da fila pode ser feita pela tela de administração do RabbitMQ no endereço: http://localhost:15672/#/queues, no item “Add a new queue”, como demonstrado na imagem abaixo:
Observação: O plugin de administração visual nem sempre está ativo na instalação, utilizando o Homebrew para instalação, esse plugin já vem ativo.
A dependência do RabbitMQ para o Spring Boot é o spring-boot-starter-amqp, que apesar do nome genérico traz funcionalidades do RabbitMQ.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> <version>1.5.8.RELEASE</version> </dependency>
Como toda aplicação Spring Boot, a configuração do RabbitMQ pode ser feita no application.properties, informando: host, port, username, password e nome da fila, que via auto-configuração a conexão com o Rabbit será inicializado.
application.properties
spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest queue.order.name=OrderQueue
Após configurado, a Queue pode ser inicializada através de um @Bean na classe de configuração do Spring Boot, assim centralizando e possibilitando injeção do objeto que representa a fila.
import org.springframework.amqp.core.Queue; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class SenderAppConfig { @Value("${queue.order.name}") private String orderQueue; public static void main(String[] args) { SpringApplication.run(SenderAppConfig.class, args); } @Bean public Queue queue() { return new Queue(orderQueue, true); }
Realizado os dois passos anteriores, a aplicação está pronta para enviar e consumir dados de filas no RabbitMQ. Vamos iniciar pelo envido de dados para fila, criando a classe OrderQueueSender, que tem como objetivo conectar no RabbitMQ e enviar mensagens para fila.
import org.springframework.amqp.core.Queue; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class OrderQueueSender { @Autowired private RabbitTemplate rabbitTemplate; @Autowired private Queue queue; public void send(String order) { rabbitTemplate.convertAndSend(this.queue.getName(), order); } }
- RabbitTemplate: É uma classe helper para acessar e enviar mensagens para RabbitMQ de forma síncrona;
- Queue: É um objeto que representa a fila configurada;
- rabbitTemplate.convertAndSend: Método possui recebe os parâmetro: routingKey e message, onde são o nome da filea e a mensagem a ser enviada.
Com isso, a cada chamada do método send, será enviado uma mensagem para fila, no caso do exemplo acima, o pedido(order) será enviando no corpo da mensagem para o RabbitMQ na fila OrderQueue.
No plugin de administração visual, há um dashboard com todas as informações para monitorar a fila, como demostrado abaixo:
Para consumir a fila, a dependência do spring-boot-starter-amqp, disponibiliza a anotação @RabbitListener que recebe como parâmetro um array de String, que são os nomes da filas que serão consumidas, dessa forma, quando inicializado a aplicação o método anotado começará a consumir a fila.
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.Headers; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; import java.util.Map; @Component public class OrderConsumer { @RabbitListener(queues = {"${queue.order.name}"}) public void receive(@Payload String fileBody) { log.info("Order: " + order); } }
-
- @Component: O consumer deve ser um bean mapeado no Spring, por isso anotado como componente;
- @RabbitListener: É a anotação que marca o método como um listener;
- @Payload: É a anotação que informa que o parâmetro vai receber o corpo da mensagem. Observação: não é obrigatório quando tem apenas um parâmetro.
Por padrão, a anotação @RabbitListener instância apenas um consumer, ou seja, não trabalha com concorrência na leitura da fila, caso seja necessário mudar esse comportamento, configurar as propriedades spring.rabbitmq.listener.simple.concurrency e spring.rabbitmq.listener.simple.max-concurrency no application.properties.
O único pré-requisito para utilizar essa anotação é ativar o Rabbit na aplicação, utilizando a anotação @EnableRabbit na classe de configuração.
import org.springframework.amqp.rabbit.annotation.EnableRabbit; import org.springframework.boot.SpringApplication; @SpringBootApplication @EnableRabbit public class ConsumerAppConfig { .....
Concluindo, o RabbitMQ é uma boa alternativa de message broker, pois além de simples de utilizar e configurar em conjunto com o Spring Boot, também apresenta um bom desempenho e com possibilidade de configurações para atender alta escalabilidade.
O código fonte dos exemplos estão disponíveis no github.
Emmanuel parabéns.
O post está simples e objetivo, acredito que melhor que muitos exemplos que tinha lido antes.
CurtirCurtir
Obrigado! Fico feliz em ajudar.
CurtirCurtir
muito simples e direto!
CurtirCurtir
Que bom! Fico feliz em ajudar!
CurtirCurtir
Muito bom simples e direto!
CurtirCurtir
Que bom! Fico feliz em ajudar!
CurtirCurtir
Achei interessante esse exemplo porque não há o binding explicitamente com o exchange. Agora estou tentando criar um consumer dinamicamente
CurtirCurtir
Obrigado por compartilhar conhecimento, excelente post, parabéns!
CurtirCurtir
Obrigado pelo feedback Andre!
CurtirCurtir
qual a diferenca entre essas duas dependencias?
spring-boot-starter-amqp vs spring-cloud-starter-stream-rabbit
CurtirCurtir
Opa Tiago, a dependência spring-boot-starter-amqp é uma lib para trabalhar com AMQP independente do tipo da troca de mensagem, por exemplo com queues e/ou exchanges, já a dependência spring-cloud-starter-stream-rabbit é para trabalhar especificamente com fluxos contínuos de dados (os streams), por exemplo com exchanges ou tópicos
CurtirCurtir