Pular para o conteúdo principal

Conceitointermediário

Poison Messages

Visão Geral

Uma poison message é uma mensagem que falha em toda tentativa de processamento.

Sem tratamento, ela volta para a fila indefinidamente, consome o consumidor, e — em filas com ordem — bloqueia todas as mensagens seguintes.

É o modo de falha mais comum de sistemas de mensageria recém-adotados, e o mais fácil de prevenir.

Problema

O consumidor lê a mensagem, tenta processar, lança exceção. Não confirma. A mensagem volta a ficar visível. Outro consumidor a lê. Mesma exceção.

Enquanto isso, nada mais é processado — ou porque a mensagem ocupa o consumidor em laço, ou porque a fila preserva ordem e ela é a próxima.

O sistema não emite erro visível. Do lado de fora, ele parece funcionar: o consumidor está de pé, o broker está de pé, a fila apenas para de avançar.

Isso é descoberto horas depois, tipicamente por alguém perguntando por que um pedido não foi processado.

Conceitos Centrais

As causas

Dado malformado. Um campo com formato inesperado, caractere inválido, codificação errada.

Mudança de esquema. O produtor passou a enviar um formato que o consumidor não entende. Ver evolução de schema.

Defeito no consumidor. Um caso não previsto que sempre lança.

Precondição permanentemente ausente. A mensagem referencia uma entidade que não existe e nunca existirá.

Note que a última é ambígua: pode ser desordem — a entidade ainda vai chegar — ou permanente. Distinguir exige contexto que o consumidor nem sempre tem.

Transitória versus permanente

A decisão central do consumidor a cada falha: isto vai funcionar se eu tentar de novo?

FalhaNatureza
Banco indisponível, timeout de redeTransitória — repita
Serviço externo com erro 503Transitória
Erro de desserializaçãoPermanente — não repita
Validação de negócio rejeitouPermanente
Entidade referenciada não existeAmbígua

Repetir uma falha permanente é desperdício garantido. Tratar uma transitória como permanente descarta trabalho que teria sucesso.

O consumidor precisa classificar — e o padrão de "tente três vezes e mande para dead-letter" trata todas igual, o que é aceitável como rede de segurança e ruim como estratégia única.

Limite de tentativas é obrigatório

Toda mensagem precisa de um contador. Após N tentativas, ela sai da fila principal para uma dead-letter queue.

Sem limite, o laço é infinito. Com limite mas sem dead-letter, a mensagem é descartada silenciosamente — o que troca um problema visível por um invisível.

Falha no envenenamento pode não estar na mensagem

Caso traiçoeiro: a mensagem está correta e o consumidor tem um defeito que só aparece com aquele conteúdo.

Nesse caso, mandar para dead-letter é o comportamento certo, e a análise precisa olhar o consumidor, não a mensagem. Um lote de mensagens envenenadas com o mesmo padrão é sinal disso.

Isolamento do bloqueio

Em filas sem ordem garantida, uma mensagem envenenada ocupa um consumidor mas não impede os outros de avançarem. O impacto é de capacidade.

Em filas com ordem por partição, ela bloqueia a partição inteira. Todas as mensagens da mesma chave param.

Isso muda a urgência: num sistema com ordem, uma mensagem envenenada é incidente, não degradação.

Modelo Mental

Toda mensagem precisa de um caminho de saída da fila — por sucesso ou por desistência. Sem o segundo, ela fica para sempre.

Quando Usar

O tratamento é obrigatório em qualquer consumidor. As decisões que restam:

  • Quantas tentativas antes de desistir.
  • Se classificar falhas por natureza ou tratar todas igual.
  • Para onde a mensagem vai ao desistir.

Quando Não Usar

Repetir indefinidamente. Nunca é a resposta.

Descartar sem registrar. Perde a informação e esconde o problema.

Tratar toda falha como permanente. Descarta trabalho que teria sucesso na segunda tentativa.

Tratar toda falha como transitória. Repete erro de desserialização três vezes, sem chance de sucesso.

Sem alerta. Uma dead-letter queue que ninguém monitora é um cemitério.

Alternativas

  • Dead-letter queue — a resposta padrão.
  • Fila de reprocessamento com atraso — para falhas ambíguas, tentar de novo daqui a horas em vez de descartar.
  • Validação no produtor — impedir que a mensagem malformada entre. É a prevenção, e não elimina a necessidade do tratamento.
  • Registro de esquema — garantir compatibilidade entre produtor e consumidor.

Trade-offs

Poucas tentativasMuitas
Sai rápido da filaOcupa por mais tempo
Falha transitória longa vira dead-letterMais chance de sucesso
Menos consumo de recursoMais
Classificar a falhaTratar todas igual
Sem retentativa inútilSimples
Exige mapear os errosNada a manter
Sai mais rápido no caso permanenteSempre N tentativas

Modos de Falha

Laço infinito. Sem limite de tentativas.

Partição bloqueada. Em fila com ordem, tudo da mesma chave para.

Descarte silencioso. Sem dead-letter nem registro.

Dead-letter não monitorada. As mensagens vão para lá e ninguém olha.

Retentativa de erro de desserialização. Três tentativas garantidamente inúteis.

Envenenamento em massa. Uma mudança de esquema envenena todas as mensagens de uma vez, e a dead-letter recebe milhares.

Erros Comuns

Não configurar limite de tentativas.

Não distinguir transitório de permanente.

Não alertar sobre a dead-letter.

Não registrar o conteúdo e o erro. Sem isso, diagnosticar exige reproduzir.

Não testar o caminho de falha. É o caminho que só acontece quando algo está errado.

Exemplo Real

Um consumidor de eventos de pedido processava a integração fiscal.

Um pedido com um caractere de controle no campo de observação fazia a serialização do payload fiscal lançar exceção.

A fila tinha ordem por partição, particionada por filial. A mensagem envenenada bloqueou a partição daquela filial.

Nove horas de emissões paradas. Foram descobertas quando a filial ligou perguntando por que nenhuma nota estava saindo.

O consumidor estava de pé. O broker estava de pé. Não havia erro em nenhum painel — apenas uma partição que não avançava, e não havia métrica de idade da mensagem mais antiga por partição.

Quatro correções.

Dead-letter após três tentativas, com o conteúdo original e o erro registrados.

Classificação de falha: erro de serialização e de validação vão direto para dead-letter, sem retentativa. Falha de rede e de banco tentam três vezes.

Alerta duplo: qualquer mensagem na dead-letter dispara aviso, e a idade da mensagem mais antiga por partição acima de 15 minutos dispara alerta.

Sanitização no produtor. Caracteres de controle passaram a ser removidos na origem — a prevenção, que não substitui o tratamento.

Nos dois anos seguintes, a dead-letter recebeu 34 mensagens. Todas foram analisadas em minutos, e nenhuma bloqueou nada.

A avaliação posterior aponta: as quatro correções custaram um dia de trabalho, e todas estavam na documentação do serviço de fila. O incidente de nove horas foi inteiramente evitável com configuração padrão de boa prática.

Conceitos Relacionados

Exercício Prático

Para cada consumidor do seu sistema, verifique: existe limite de tentativas? Existe dead-letter? Existe alerta sobre ela?

Depois publique deliberadamente uma mensagem malformada em ambiente de teste e observe. Se a fila travar, você reproduziu o incidente antes dele acontecer.

Perguntas de Entrevista

  • O que acontece com uma mensagem que sempre falha, sem tratamento?
  • Como distinguir falha transitória de permanente no consumo?
  • Por que o bloqueio é mais grave em fila com ordem?

Para Aprofundar

  • Hohpe, Gregor; Woolf, Bobby. Enterprise Integration Patterns, 2003 — o padrão Dead Letter Channel.
  • Nygard, Michael. Release It! 2ª ed., 2018.
Terminou de ler este documento?Seu progresso fica salvo apenas neste navegador.