Progettazione di un meccanismo di ripetizione scalabile e robusto

5

Backstory

Possiedo un'applicazione del server di messaggistica responsabile dell'intermediazione / proxy delle chiamate effettuate da un livello applicazione a numerosi servizi esterni. Lo scopo di questa applicazione è di astrarre gli aspetti tecnici del richiamo di questi servizi lontano dal livello di applicazione principale.

Funziona bene poiché l'Application Server non deve preoccuparsi dei protocolli http / ldap ecc, wcf, ftp, soap, ebxml, ecc. Semplicemente inviano un "payload", con pochi identificatori, e il server Messaging gestisce il riposo. Significa anche che se una definizione del servizio cambia, il server delle applicazioni non deve essere modificato. Inoltre, il server di messaggistica viene chiuso da un database SQL 2008 che archivia una verifica di tutti i messaggi inviati e le risposte associate, ecc.

L'architettura generale del flusso di dati di questo è la seguente:

Application Server (s) = > Load Balancer = > Server di messaggistica = > [X] = > Servizi esterni

La domanda

Devo implementare un meccanismo di tentativi nel livello dell'applicazione di messaggistica. L'intenzione è di ripristinare con garbo le situazioni in cui il server di messaggistica non è in grado di inoltrare il servizio di destinazione (ovvero servizio inattivo, problemi di rete, timeout, ecc.), I problemi con il punto [X] nell'architettura sopra.

Il requisito di progettazione di alto livello è:

Application Server invia una richiesta al server di messaggistica. Questo quindi tenta di inoltrare ai servizi esterni. Se il primo tentativo non riesce, il server di messaggistica risponde in modo sincrono all'application server affermando che il messaggio è "in riprova"

Il server di messaggistica procede quindi a riprovare l'intemperie per il contratto (ad esempio, X tentativi con Y secondi tra ciascuno).

Una delle due cose succederà dopo, tutti i tentativi contrattuali saranno stati eseguiti senza successo o uno dei tentativi avrà esito positivo. In entrambi i casi, un messaggio viene inviato di nuovo nel livello applicazione per notificare lo stato della richiesta di messaggistica.

Alcuni gothcas

Il messaggio da riprovare non può essere trattenuto nella "memoria" come se il server di messaggistica non fosse attivo. Inoltre, un contratto di ripetizione può essere 5 volte una volta ogni 12 ore, non è possibile tenere i dati in memoria per quel periodo di tempo. Ciò detto, alcuni contratti di ripetizione potrebbero essere 5 volte una volta ogni 5 secondi.

Se la rete di inoltro si interrompe e quindi recupera il carico dei tentativi, deve essere distribuito su tutto il livello di messaggistica anziché su un singolo server.

La domanda

La comunicazione tra il livello di applicazione e di messaggistica non è una preoccupazione poiché tale struttura è già in atto. Tuttavia, l'architettura del retry framework nel livello di messaggistica è ancora nell'aria. Come implementeresti questo?

Opzioni che abbiamo / stiamo considerando

In caso di errore, memorizza i dati di prova in un database, quindi disponi di un servizio di polling che controlla il database ogni secondo. Se viene trovato un messaggio pianificato per il tentativo, questo viene reindirizzato al livello di messaggistica tramite Load Balancer

In caso di errore archiviare i dati di tentativi in un database, utilizzare un lavoro CLR per eseguire il polling del database e inviare i messaggi, pianificati per riprovare, nuovamente su Load Balancer

Altre informazioni

Può o potrebbe non essere pertinente:

  • Tutto il codice è C #
  • I database sono SQL 2008
  • Le comunicazioni da livello Application a Messaging vengono eseguite tramite WCF con BasicHttpBinding.
  • Abbiamo il controllo completo su tutti gli aspetti del livello del server di messaggistica e nessun controllo sul livello applicazione.
  • Il livello di messaggistica attualmente gestisce circa 500k transazioni all'ora, quindi puoi immaginare quanto velocemente le cose verranno sottoposte a backup in caso di errore su uno dei servizi esterni
posta MrEyes 12.02.2012 - 01:03
fonte

1 risposta

3

Considera un timeout di tentativo esponenziale

Nella soluzione che hai fornito sopra con un meccanismo di tentativi ogni 1 secondo è una soluzione ingenua.

Dovresti considerare un aumento esponenziale del tempo fino a un massimo (deciso dall'azienda).

Si tratta di evitare situazioni in cui si stanno spendendo cicli preziosi nel polling di un numero sempre crescente di messaggi arretrati che falliranno e rallenteranno l'elaborazione dei messaggi che possono essere gestiti ed elaborati immediatamente.

Messaggi avvelenati

È possibile che vengano visualizzati messaggi avvelenati. Questi messaggi potrebbero non essere mai in grado di essere elaborati per un motivo o per un altro. Dovresti considerare di avere un processo in atto per identificare e gestire questi messaggi.

Questa è una decisione aziendale, non un dettaglio di implementazione

Penso che la domanda più pertinente non sia quella che viene detta qui, ma che cosa vuole fare l'azienda in questa situazione? Come effettivamente creare un meccanismo di polling di nuovo tentativo è banale. Ciò che l'azienda vuole fare in quella situazione non è, ed è puramente una decisione commerciale.

Esempio di mondo reale

Ho scritto un sistema distribuito per il mio datore di lavoro un certo numero di anni fa (MSMQ, C #, ecc.). Ho implementato un sistema in cui i messaggi avrebbero un meccanismo di ripetizione che riproverà utilizzando una funzione esponenziale fino a raggiungere un massimo di una volta all'ora.

Ho installato un monitor NAGIOS che esegue il polling e quindi rileva il numero di messaggi non riusciti nella coda e quindi invia un avviso se raggiunge una determinata soglia. Ciò avviserebbe immediatamente l'azienda che un venditore era offline e che i clienti che si aspettavano un'inversione di tendenza lasciano dire un'ora.

Sarebbe quindi una decisione commerciale (in questo caso l'azienda ha deciso di cancellare tutti questi arretrati in coda di messaggi e poi gestirli manualmente tramite l'helpdesk). E così l'applicazione doveva essere scritta per essere in grado di consentire l'elaborazione manuale di questi messaggi.

In altri casi in cui il fornitore era solo offline per alcuni minuti, il meccanismo dei tentativi lo raccoglieva e li gestiva normalmente. Tuttavia, il timeout esponenziale consentiva al sistema di elaborare con garbo le transazioni regolari e il backlog senza far nevicare il server quando il venditore tornava online.

    
risposta data 12.02.2012 - 02:57
fonte

Leggi altre domande sui tag