Criando um mecanismo de repetição escalável e robusto

5

História anterior

Eu tenho um aplicativo de servidor de mensagens que é responsável pela intermediação / intermediação de chamadas feitas de um nível de aplicativo para vários serviços externos. O objetivo desta aplicação é abstrair os detalhes técnicos de invocar esses serviços longe da camada principal do aplicativo.

Isso funciona bem, pois o Application Server não precisa se preocupar com protocolos http / ldap etc, wcf, ftp, soap, ebxml etc. etc. Eles simplesmente enviam uma "carga útil", com alguns identificadores, e os manipuladores do Servidor de Mensagens. o resto. Isso também significa que, se uma definição de serviço for alterada, o Application Server não precisará ser alterado. Além disso, o Servidor de Mensagens é finalizado por um banco de dados do SQL 2008 que armazena uma auditoria de todas as mensagens enviadas e respostas associadas, etc.

A arquitetura geral do fluxo de dados é a seguinte:

Servidor (es) de aplicativos = > Balanceador de carga = > Servidor de Mensagens (s) = > [X] = > Serviços Externos

A questão

Eu preciso implementar um mecanismo de repetição na camada do aplicativo de mensagens. A intenção é se recuperar de situações em que o Messaging Server não é capaz de encaminhar para o serviço de destino (ou seja, serviço inativo, problemas de rede, tempos limite, etc.), ou seja, problemas com o ponto [X] na arquitetura acima.

O requisito de design de alto nível é:

O Application Server envia uma solicitação ao Servidor de Mensagens. Isso, então, tenta encaminhar para os serviços externos. Se a primeira tentativa falhar, o Servidor de Mensagens responderá de maneira síncrona ao Servidor de Aplicativos informando que a mensagem está "em nova tentativa"

O Servidor de Mensagens continua a tentar novamente o cumprimento do contrato (ou seja, X tenta novamente com Y segundos entre cada um).

Uma das duas coisas acontecerá a seguir, todas as novas tentativas contratadas terão sido realizadas sem sucesso ou uma das tentativas será bem-sucedida. Em ambos os casos, uma mensagem é enviada de volta para o nível de aplicativo para notificar o estado da solicitação de mensagens.

Algumas gothas

A mensagem para tentar novamente não pode ser mantida em "memória", como se o Servidor de Mensagens falisse, a mensagem fosse perdida. Além disso, um contrato de repetição pode ser 5 vezes a cada 12 horas, mantendo os dados na memória por esse período de tempo não é viável. Dito isso, alguns contratos de repetição podem ser 5 vezes a cada 5 segundos.

Se a rede de encaminhamento ficar inativa e, em seguida, recuperar a carga das novas tentativas, ela deverá ser distribuída por toda a camada de mensagens, em vez de um único servidor.

A questão

A comunicação entre o nível de aplicativo e de mensagens não é uma preocupação, já que esse framework já está em vigor. No entanto, a arquitetura do novo framework no Messaging Tier ainda está no ar. Como você implementaria isso?

Opções que consideramos

Em caso de falha, armazene os dados de nova tentativa em um banco de dados e, em seguida, tenha um serviço de pesquisa que verifique o banco de dados a cada segundo. Se for encontrada uma mensagem que esteja agendada para nova tentativa, retorne para o Nível de Mensagens por meio do Balanceador de Carga

Em caso de falha, armazene os dados de nova tentativa em um banco de dados, use um trabalho CLR para pesquisar o banco de dados e envie as mensagens, agendadas para nova tentativa, de volta para o Load Balancer

Outras informações

Pode ou não ser relevante:

  • Todo o código é C #
  • Bancos de dados são SQL 2008
  • Comms de Application to Messaging são executados via WCF com BasicHttpBinding.
  • Temos controle total sobre todos os aspectos da camada do Servidor de Mensagens e nenhum controle sobre a Camada de Aplicativo.
  • O nível de mensagens gerencia atualmente cerca de 500 mil transações por hora, então você pode imaginar a rapidez com que as coisas serão copiadas se houver uma falha em um dos serviços externos
por MrEyes 12.02.2012 / 01:03
fonte

1 resposta

3

Considere um tempo limite de repetição exponencial

Na solução que você forneceu acima, ter um mecanismo de repetição a cada 1 segundo é uma solução ingênua.

Você deve considerar um aumento de tempo exponencial até um máximo (decidido pela empresa).

Isso é para evitar situações em que você está gastando ciclos valiosos na pesquisa de um registro posterior de mensagens cada vez maior, que só irá falhar e retardar o processamento de mensagens que podem ser manipuladas e processadas imediatamente.

Mensagens envenenadas

É possível que mensagens envenenadas sejam exibidas. Essas mensagens talvez nunca possam ser processadas por um motivo ou outro. Você deve considerar ter um processo para identificar e lidar com essas mensagens.

Esta é uma decisão de negócios, não um detalhe de implementação

Eu acho que a questão mais pertinente não é o que é dito aqui, mas o que a empresa quer fazer nessa situação? Como realmente criar um mecanismo de pesquisa de repetição é trivial. O que a empresa quer fazer nessa situação não é, e é puramente uma decisão comercial.

Exemplo do mundo real

Eu escrevi um sistema distribuído para o meu empregador há alguns anos (MSMQ, C #, etc). Implementei um sistema em que as mensagens teriam um mecanismo de repetição que tentaria usar uma função exponencial até atingir o máximo de uma vez por hora.

Eu tinha um monitor NAGIOS no lugar que iria pesquisar e, em seguida, detectar o número de mensagens com falha na fila e, em seguida, enviar um alerta se ele atingisse um determinado limite. Isso alertaria instantaneamente a empresa de que um fornecedor estava off-line e que os clientes que esperariam uma recuperação de tempo digam uma hora.

Seria então uma decisão comercial (nesse caso, a empresa decidiu cancelar todos esses backlog enfileirados de mensagens e, depois, manipulá-los manualmente por meio do suporte técnico). E assim o aplicativo teve que ser escrito para permitir o processamento manual dessas mensagens.

Em outros casos em que o fornecedor ficou off-line por alguns minutos, o mecanismo de novas tentativas os recuperou e os manipulou de acordo com o normal. No entanto, ter o tempo limite exponencial permitiu que o sistema processasse normalmente as transações regulares e o backlog sem nevar o servidor quando o fornecedor voltasse a ficar on-line.

    
por 12.02.2012 / 02:57
fonte