É comum falarmos sobre receitas de sucesso e como resolver problemas, mas será que você está fazendo essas coisas, está perdendo mensagens e vai culpar o RabbitMQ por isso?
Se liga nessas dicas, pois se você está perdendo mensagens com RabbitMQ, a culpa é totalmente sua! E vou mostrar como você pode perder mensagens para que isso não ocorra mais.
Por que mensagens são perdidas?
O RabbitMQ é um eficiente message broker, no entanto você precisa ficar atento à forma de uso, pois ele não te obriga e nem possui configuração que evite, by default, que você tome decisões de implantação ou uso erradas. Assim como um banco de dados oferece transações, mas não obriga a usá-las.
As mensagens são perdidas pois o RabbitMQ oferece modelos permissivos em que você pode desligar controles dele. E isso pode ser feito das mais variadas formas. Cada vez que você desabilita algum controle, no final das contas você está ganhando mais performance. E quando os benefícios são superiores aos riscos, é o momento de desabilitar uma feature ou outra.
O problema é que a maioria de nós, desativa features de segurança, ou melhor, não as habilita, porque lemos apenas um tutorial meia boca que visa fazer um get started e presumimos que aquilo é tudo. É o famoso: “Ahhh já sei!”. Depois dá merda, perde mensagens e a culpa é do RabbitMQ. Nana-nina-não! A culpa é toda sua por não ter passado da segunda página ou ter apenas ficado em um tutorial aqui ou acolá.
Como perder mensagens:
As mensagens são perdidas por alguns fatores:
Filas não duráveis
As filas podem ser duráveis ou não. Filas não duráveis não são persistidas. Isso quer dizer que você tem quase e não todos os controles que o RabbitMQ oferece, o principal controle que você perde com filas não duráveis é o controle de não perder mensagens entre restart do servidor. Ou seja, o servidor restarta e as filas não duráveis perdem todos os seus dados.
Mensagem não persistente
Toda mensagem enviada para o RabbitMQ pode ser persistente ou não. Isso fica no Delivery Mode, (exemplo). Quando você cria uma BasicProperties, você tem a oportunidade de definir um DeliveryMode para a mensagem. Ignorar a existência de uma BasicProperty ou não setar o DeliveryMode para 2, é um bom fator para você perder mensagens.
TTL agressivo demais
Uma das configurações que uma fila possui é o TTL (Time to Live) ou tempo de vida. Isso determina que uma mensagem dura apenas X tempo em uma fila, após esse tempo ela é dada como processada. A documentação oficial ainda aborda como você configura políticas, e fala também da configuração por mensagem. Aliás esse tópico poderia ser dividido em 2:
- TTL na Fila
- TTL na Mensagem
Pois você pode definir um tempo de vida específico para cada um. Assim a mensagem pode ter seu TTL específico enquanto a fila pode definir também um TTL padrão.
Autoack
Os dois primeiros erros são menos comuns, pois em geral você quer filas duráveis, e configura certo desde o início, TTL não é algo comum para projetos que estão começando a adoção de RabbitMQ. Mas AutoAck é um inferno para perder mensagens.
AutoAck e Never Exceptions (nunca lançar exceções) são uma dobradinha fatal que juntas podem culminar (e geralmente culminam) em mensagens sendo perdidas de uma forma incrível. É como areia escorrendo pelas mãos, incontrolável.
Durante o consumo você pode escolher trabalhar com ack manual ou autoack. E estamos falando de uma diferença tão pequena.
Mas o que significa o AutoAck? Acknowledgements (acks) é como um commit de uma transação. Só que pela perspectiva do RabbitMQ significa: Hey Rabbit, pode apagar essa mensagem, tá tudo ok por aqui!
O problema é o momento em que você manda esse Ok!
Com AutoAck, você envia o ack quando a mensagem chega no consumidor, ou seja antes de começar o processamento. Isso quer dizer que a mensagem é apagada no RabbbitMQ antes mesmo de começar a ser processada. Consequentemente, a mensagem só existe na memória do processo que pegou a mensagem. Ela não existe mais em lugar algum.
Dessa forma a menor falha, produzirá a perda da mensagem.
E daqui pra frente começam as gambiarras para fazer porcamente o que o RabbitMQ já faz com graciosidade. E o céu é o limite.
Conclusão
O RabbitMQ é um message broker incrível, simples de usar e simples de gerenciar. A natureza de tender a ter zero mensagens nas filas facilita muito a adoção de mensageria por novos times.
Mas como qualquer coisa, exige conhecimento específico.
Os erros humanos no uso do RabbitMQ são muitos, mas para nossa sorte, são sempre muito previsíveis e isso facilita tudo.
Você não precisa de muito tempo para dominar RabbitMQ. São poucos e poderosos recursos.
UPDATE 08/09/2020 | 01:00 – Adicionando mensagens não persistentes!!!
Luiz, é possível tirar um broker do cluster, e rodá-lo standalone sem perder as mensagens contidas nele?
Danilo, nunca fiz não. Suba um novo cluster temporário com a mesma versão e teste.