Eu tenho um sistema Java usando o ActiveMQ para mensagens. E o sistema processa cerca de 400 a 600 transações por segundo e não temos problemas quando tudo está funcionando sem problemas. O sistema também conseguiu enviar essas transações para um sistema externo.
Quando o sistema externo fica inoperante por um tempo prolongado (digamos uma ou duas horas), o que fazemos é remover mensagens com falha que não foram enviadas com êxito ao sistema externo durante a interrupção para uma fila (o que chamamos de fila de repetição) .
Precisamos processar essas mensagens em tempo hábil, para que possamos dar tempo suficiente ao sistema externo para se recuperar.
Tentamos várias abordagens e nenhuma parece funcionar perfeitamente. A maioria deles funciona quando lidamos com um número menor de mensagens.
Abordagem 1: Usamos o atraso do ActiveMQ onde definimos o carimbo de data / hora no cabeçalho JMS (consulte aqui para obter mais detalhes: http://activemq.apache.org/delay-and-schedule-message-delivery.html ) e funcionou quando existem algumas centenas ou milhares de mensagens na fila.
Descobrimos perda de mensagens quando havia cerca de 500 mil mensagens ou mais. Descobrimos que as mensagens aparecem misteriosamente sem nos dar nenhuma pista.
Por exemplo, vejo que as mensagens desapareceram mesmo para 20k.
Definimos o atraso como 5 minutos, para que as mensagens sejam tentadas até 12 vezes em uma hora. Quando o sistema externo ficou inativo por uma hora, esperávamos que todas as 20 mil mensagens fossem repetidas pelo menos 12 vezes.
O que observamos foi que, quando consumimos a cada 5 minutos:
Tentativa 1: 20k mensagens Tentativa 2: 20k mensagens
Tentativa 7: 19987 mensagens Tentativa 10: 19960 mensagens Tentativa 12: 19957 mensagens
Às vezes, todas as 20 mil mensagens foram processadas, mas os resultados do teste foram inconsistentes.
Abordagem # 2:
Usamos a política de devolução do ActiveMQ, onde definimos a política no nível da fábrica de conexões, fazemos a sessão ser transacionada, lançamos uma exceção quando o sistema externo está inativo, para que o broker continue entregando novamente as mensagens com base na configuração da política de devolução. Essa abordagem também não funcionou bem quando a interrupção durou mais tempo e precisamos ter consumidores sem bloqueio. Ele funciona no próprio nível da fila de despacho, sobrecarregando a fila quando há muitas transações recebidas.
Abordagem # 3:
Usamos o agendador Quartz, que acorda a cada X minutos e cria conexão, os consumidores obtêm mensagens da fila de repetição, tentam processá-las ainda mais e, se o sistema externo ainda estiver inativo, colocam a mensagem com falha na parte de trás da fila. Essa abordagem tem muitos problemas que nos forçaram a gerenciar conexões, consumidores etc.,
Por exemplo, quando há algumas mensagens na fila, quando temos mais consumidores que o número de mensagens, isso resulta em uma mensagem recebida pelo consumidor, novamente o mesmo consumidor retornando a mensagem para Repetir (como o o sistema externo ainda está inativo), com outro consumidor atendendo, resultando em viagens de mensagens entre consumidor e corretor.
Abordagem # 4:
Tentamos armazenar as mensagens com falha no banco de dados e o agendador de quartzo é executado a cada X minutos para coletar as mensagens do banco de dados.
Isso não é otimizado, pois envolve muita verificação de transação entre os consumidores do banco de dados que estão sendo executados em vários nós e o banco de dados.
Meu ambiente é Java, JBoss, ActiveMQ 5.9, MySQL 5.6 e Spring 3.2.
Passei por várias outras abordagens, como o modelo de nova tentativa (do Spring) e o padrão de nova tentativa assíncrona com o Java 7/8
Minha opinião sobre o problema é que a maioria das soluções funciona quando há carga mínima e parece que elas quebram quando a interrupção dura mais ou quando o volume de mensagens é realmente alto.
Estou procurando algo em que possa armazenar e encaminhar mensagens com falha. Para um sistema de 400 TPS, em uma hora, posso receber 1,44 milhão de mensagens.
Se o sistema externo estiver inoperante, como processarei essas 1,44 milhão de mensagens, dando a cada mensagem a mesma chance de serem repetidas sem perder mensagens ou desempenho.
Estou procurando uma solução dentro do escopo do ambiente que tenho.