Vamos às principais perguntas e respostas sobre RabbitMQ e mensageria em geral.
Fugirei das formalidades e serie mais raso nas argumentações. A tentativa é de deixar as respostas mais claras.
Como eu pego uma mensagem na fila?
Esse nem é uma dúvida, é um erro de principiante mesmo, natural, comum, típico, mas muito nocivo.
Então você instalou o RabbitMQ ou subiu em um container, criou um projeto de exemplo e acabou de adicionar o pacote nugget.
Após criar a conexão e o model a primeira coisa que se busca na api é um método GET qualquer para pegar uma mensagem em uma fila. Estratégia errada!
Você até tem disponível o BasicGet para isso. Mas provavelmente você NUNCA usará-lo, NUNCA!! Ok?! Vamos combinar assim!?
No client para .NET temos os consumers, que são classes que gerenciam uma conexão persistente com o RabbitMQ, na prática você pluga sua implementação em um evento de uma classe que fica escutando uma ou mais filas. Isso quer dizer que você não implementa um While(true) pra pegar mensagens da fila. Você trabalha de forma reativa, conectado à fila. É responsabilidade do Consumer gerenciar a quantidade de threads, portanto é possível que em algum momento mais à frente você até pense em criar um worker próprio.
AutoAck é vida, pra que fazer na mão se posso configurar no provider?
No RabbitMQ há um comando chamado acknowledge, apelidado de Ack, que emite uma notificação para o servidor informando que a mensagem já pode ser descartada. Novamente recorrendo a analogias: é como o Commit de uma transação sql.
O ponto é que se você não controla, quem controla é outro alguém. E é aí que mora o problema. Esse alguém não sabe se você acabou ou não o processamento, portanto delegar essa decisão pode resultar na perda de mensagens nos casos de exceptions, crashes e kills. Nesse caso em que você não tem o controle, o ack acontece antes de você acabar o processamento e é aí que mora o problema.
Esse tema será abordado no próximo post.
Como assim eu não posso fazer query na fila para pegar uma mensagem que está no meio dela?
É verdade. Fila não é um banco. Filas trabalham sob o modelo First In, First Out! Mas no envio você consegue definir prioridade, o que muda o jogo, no entanto você não consegue fazer update na mensagem para mudar sua prioridade. Imutabilidade é levado ao nível máximo.
O que acontece com as mensagem que são expurgadas, ou morrem na fila, elas desaparecem, se o RabbitMQ explodir com disco e tudo eu perdi tudo?
Depende da estratégia que usou. Em geral, nas minhas implementações, as mensagens que estão na fila são representações de algo persistido em um repositório de longa duração.
Eu considero 2 tipos de filas, esses são tipos que criei na minha cabeça. Não estão documentados em lugar algum. Mas elas expressam 2 questões diferentes:
- Filas que trabalham mensagens que só existem na fila, portanto perda de mensagem produz perda para o negócio.
- Filas que trabalham mensagens que estão persistidas em algum lugar e preciso processar uma etapa de um fluxo.
Eu tenho muito cuidado com esse primeiro tipo de fila, e quando posso, sequer tenho. Nesses casos, eu uso algum storage que privilegie a escrita em detrimento da leitura, somente para garantir que a mensagem esteja em um repositório, persistida definitivamente o mais rápido possível. Essas são as filas que mais me preocupam.
Já as filas de processamento comum, eu tenho algumas variações na forma de uso:
- A mensagem está inteira na fila: Isso quer dizer que quem vai processar não precisa fazer nada além de receber a mensagem, processá-la, e chamar o ack no final (não faz diferença se a mensagem está ou não em um repositório)
- A mensagem é uma referência para um dado: isso quer dizer que a mensagem só tem referência para um dado que está em um repositório, assim, quem vai processar precisa acessar o repositório para obter a versão atual do dado a ser trabalhado.
O repositório que cito pode ser um banco, mas pode ser um Redis também, não há nada de errado nisso. E se o Redis não for confiável o suficiente para o meu cenário, posso ainda fazer um fallback, redis/db. Nada de errado nisso também, as métricas vão te dizer qual o melhor cenário para você.
O importante é saber que nem sempre você vai deixar a mensagem inteira na fila, isso é comum quando a mensagem é grande demais. RabbitMQ e filas em geral não performam tão bem com mensagens gigantes, tem dados sobre isso no site do produto.
tudo bem? gostei muito do seu site, parabéns pelo conteúdo. 😉