A integração do Spring Boot com o RabbitMQ permite a comunicação assíncrona e confiável entre serviços. Este guia aborda a configuração básica, padrões de mensagens, mecanismos de confirmação e tópicos avançados como filas de mensagens mortas.
- Configuração Básica e Padrão de Troca Direta
Para começar, adicione a dependência AMQP ao seu projeto.
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-amqp</artifactid>
</dependency>
Configure as propriedades de conexão no arquivo application.yml.
spring:
rabbitmq:
host: localhost
port: 5672
username: usuario
password: senha
virtual-host: /meu_vhost
Defina a configuração do RabbitMQ, incluindo filas, trocas e associações. O exemplo abaixo demonstar a configuração de uma troca do tipo fanout.
@Configuration
public class RabbitMqConfig {
@Bean
public Queue filaNotificacaoEmail() {
return new Queue("notificacao.email.fila", true);
}
@Bean
public Queue filaNotificacaoSms() {
return new Queue("notificacao.sms.fila", true);
}
@Bean
public FanoutExchange trocaNotificacao() {
return new FanoutExchange("troca.notificacao.broadcast");
}
@Bean
public Binding ligacaoEmail() {
return BindingBuilder.bind(filaNotificacaoEmail()).to(trocaNotificacao());
}
@Bean
public Binding ligacaoSms() {
return BindingBuilder.bind(filaNotificacaoSms()).to(trocaNotificacao());
}
}
Produtor de Mensagens
@Service
public class ProdutorNotificacoes {
private final RabbitTemplate templateRabbit;
public ProdutorNotificacoes(RabbitTemplate templateRabbit) {
this.templateRabbit = templateRabbit;
}
public void enviarNotificacao(String conteudo) {
templateRabbit.convertAndSend("troca.notificacao.broadcast", "", conteudo);
}
}
Consumidor de Mensagens
@Component
public class ConsumidorNotificacoes {
@RabbitListener(queues = "notificacao.email.fila")
public void processarEmail(String mensagem) {
System.out.println("Processando e-mail: " + mensagem);
// Lógica para envio de e-mail
}
@RabbitListener(queues = "notificacao.sms.fila")
public void processarSms(String mensagem) {
System.out.println("Processando SMS: " + mensagem);
// Lógica para envio de SMS
}
}
- Configuração de Tempo de Vida (TTL)
O tempo de vida pode ser definido por mensagem ou globalmante na fila.
TTL por Mensagem
public void enviarComTTL(String corpo) {
MessageProperties propriedades = new MessageProperties();
propriedades.setExpiration("15000"); // 15 segundos
Message mensagem = new Message(corpo.getBytes(), propriedades);
templateRabbit.convertAndSend("troca.padrao", "chave.rota", mensagem);
}
TTL na Fila
@Bean
public Queue filaComTTL() {
Map<string object=""> argumentos = new HashMap<>();
argumentos.put("x-message-ttl", 30000);
return new Queue("fila.ttl.expira", true, false, false, argumentos);
}
</string>
- Mecanismos de Confirmação de Mensagens
Para garantir a confiabilidade, ative as confirmações de publicação e retorno.
spring:
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true
Implemente os callbacks para lidar com confirmações e retornos.
@Component
public class CallbackConfirmacao implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String causa) {
if (ack) {
System.out.println("Mensagem confirmada: " + correlationData.getId());
} else {
System.err.println("Falha na confirmação: " + causa);
}
}
}
@Component
public class CallbackRetorno implements RabbitTemplate.ReturnCallback {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.err.println("Mensagem retornada: " + new String(message.getBody()));
}
}
No produtor, configure os callbacks e utilize a confirmação manual no consumidor.
Produtor com Confirmação
public void enviarComConfirmacao(String payload) {
templateRabbit.setMandatory(true);
CorrelationData dadosCorrelacao = new CorrelationData(UUID.randomUUID().toString());
templateRabbit.convertAndSend("troca.default", "rota.teste", payload, dadosCorrelacao);
}
Consumidor com Acknowledgement Manual
@RabbitListener(queues = "fila.processamento.manual")
public void handleMessage(Message message, Channel canal) throws IOException {
try {
// Processar mensagem
System.out.println("Mensagem recebida: " + new String(message.getBody()));
canal.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
canal.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
}
- Fila de Mensagens Mortas (Dead Letter Queue)
Configure uma fila para receber mensagens que falharam no processamento.
@Bean
public Queue filaPrincipal() {
Map<string object=""> argumentos = new HashMap<>();
argumentos.put("x-dead-letter-exchange", "troca.mensagens.mortas");
argumentos.put("x-dead-letter-routing-key", "rota.mensagens.mortas");
return new Queue("fila.principal.processamento", true, false, false, argumentos);
}
@Bean
public Queue filaMensagensMortas() {
return new Queue("fila.mensagens.mortas");
}
@Bean
public TopicExchange trocaMensagensMortas() {
return new TopicExchange("troca.mensagens.mortas");
}
@Bean
public Binding ligacaoMensagensMortas() {
return BindingBuilder.bind(filaMensagensMortas())
.to(trocaMensagensMortas())
.with("rota.mensagens.mortas");
}
</string>
- Considerações de Persistência e Monitoramento
Assegure a persistência de filas, trocas e mensagens para sobreviver a reinicializações do broker. Monitoramento de memória e disco é crucial para manter a saúde do sistema RabbitMQ em ambientes de produção.
- Transações Distribuídas com RabbitMQ
Utilize a confirmação de publicação e reenvio programático para garantir a entrega confiável. No consumidor, combine o manual acknowledgment com filas de mensagens mortas para evitar ciclos infinitos de retentativa.
- Propriedades de Configuração Detalhadas
Explore as diversas propriedades de configuração disponíveis no application.yml para otimizar o comportamento do produtor, consumidor e conexões.
spring:
rabbitmq:
host: localhost
port: 5672
virtual-host: /
cache:
channel:
size: 5
connection:
mode: CHANNEL
listener:
simple:
acknowledge-mode: manual
concurrency: 1
max-concurrency: 10
prefetch: 5
template:
mandatory: true
retry:
enabled: true
max-attempts: 3