Repetir design para alto volume

8

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.

serverfaces
fonte

Respostas:

1

A questão aqui é com a otimização. Quando o sistema é instalado, o aplicativo precisa ser projetado de forma a não sobrecarregar o editor e o consumidor.

Você pode ficar esperto com seu algoritmo. Se você puder classificar uma mensagem por prioridade, as mensagens com falha poderão ser salvas com uma prioridade mais baixa. Portanto, depois que o publicador publicar uma nova mensagem, ele poderá examinar a fila de prioridade mais baixa para verificar se alguma mensagem com falha precisa ser republicada e republicada.

Essa é uma abordagem bem conhecida para limitar as mensagens. Estou certo de que existem outros algoritmos de otimização que podem ser aplicados aqui com base em suas necessidades específicas.

codedabbler
fonte
0

Aqui está a suposição de que cada nó tem uma fila de mensagens e todos esses nós estão usando um banco de dados. Todos esses nós estão tentando enviar mensagens para um sistema externo.

Uma pequena mudança na terceira abordagem pode funcionar.

  1. Quando um nó inicia, crie uma tabela para armazenar apenas novas mensagens no caso de o sistema externo ficar inoperante. Digamos que o node1 tenha criado a tabela messages_node1 para armazenar mensagens.

Agora, o caso de uso é se três nós estiverem em execução repentinamente, um sistema externo ficará inoperante, e cada nó deverá armazenar mensagens recém-chegadas na tabela correspondente, em vez de enfileirar-se no MQ. Mantenha as mensagens não entregues na própria fila. o sistema externo leva para se recuperar, a fila de mensagens existente não será carregada.Uma vez que o nó perceber que o sistema externo está ativo, inicie as mensagens de enfileiramento na tabela correspondente.

Essa abordagem soluciona problemas de lote 1.Não depende do tempo de recuperação do sistema externo 2. Não falha no caso de muitas mensagens recebidas enquanto o sistema externo está inoperante. 3.O conteúdo entre nós é minimizado, pois cada nó tem sua própria tabela. 4.O pedido das mensagens é preservado até certo ponto.

Você pode escrever APIs para acionar esses eventos. Qualquer correção com a resposta de abordagem acima

Amith Manepu
fonte