Domanda

Devo creare un servizio WCF e sto utilizzando netMsmqBinding l'associazione.

Questo è un semplice servizio che passa un Dto per il mio metodo di servizio e non si aspetta una risposta.Il messaggio viene inserito in un MSMQ, e una volta raccolti inseriti in un database.

Qual è il metodo migliore per assicurarsi che nessun dato viene perso.

Ho provato i 2 seguenti metodi:

  1. Generata un'eccezione

    In questo modo il messaggio in una lettera morta coda per il manuale di lettura.Io in grado di elaborare questo quando il mio strvice inizia

  2. impostare il receiveRetryCount="3" dell'associazione

    Dopo 3 tentativi - che capita di instantanously, questo sembra lasciare il messaggio in coda, ma per colpa del mio servizio.Riavvio il mio servizio ripete questo processo.

Idealmente vorrei fare il seguente:

Tenta di elaborare il messaggio

  • Se questo non funziona, attendere 5 minuti per il messaggio e riprovare.
  • Se il processo non riesce 3 volte, spostare il messaggio in una lettera morta coda.
  • Riavviare il servizio di spingere tutti i messaggi dalla lettera morta, con la coda in coda in modo che possa essere elaborato.

Posso realizzare questo?Se sì, come?Può indicarmi per gli articoli su come meglio utilizzare WCF e MSMQ per il mio dato sceneria.

Qualsiasi aiuto sarebbe molto apprezzato.Grazie!

Alcune informazioni aggiuntive

Sto usando MSMQ 3.0 su Windows XP e Windows Server 2003.Purtroppo non è possibile utilizzare il costruito nel veleno messaggio di sostegno mirate a MSMQ 4.0 e Vista/2008.

È stato utile?

Soluzione

C'è un campione in SDK che potrebbero essere utili nel tuo caso.Fondamentalmente, ciò che fa è di collegare un IErrorHandler attuazione al vostro servizio, che cattura l'errore quando WCF dichiara che il messaggio da "veleno" (cioèquando configurare tutti i tentativi sono stati esauriti).Quello che il campione non è spostare il messaggio in un'altra coda e quindi riavviare il ServiceHost associato con il messaggio (in quanto permette di avere in errore quando il veleno messaggio è stato trovato).

Non è un ottimo esempio, ma può essere utile.Ci sono un paio di limitazioni, anche se:

1 - Se hai più di un endpoint associati con il vostro servizio (per es.esposti attraverso varie code), non c'è modo di sapere quale sia la coda il veleno messaggio arrivato.Se si dispone solo di una singola coda, questo non sarà un problema.Non ho visto alcun ufficiale di una soluzione per questo, ma ho sperimentato con una possibile alternativa che ho descritto qui: http://winterdom.com/weblog/2008/05/27/NetMSMQAndPoisonMessages.aspx

2 - una Volta che il problema messaggio viene spostato in un'altra coda, diventa la vostra responsabilità, quindi è a voi per spostare la coda di elaborazione di una volta che il timeout è fatto (o allegare un nuovo servizio per la coda per la sua gestione).

Per essere onesti, in entrambi i casi, si sta guardando qualche "manuale" lavoro qui che WCF non copre su di essa la propria.

Sono stato recentemente a lavorare su un altro progetto in cui ho un obbligo di controllare in modo esplicito come spesso tentativi accadere, e la mia attuale soluzione è stata quella di creare una serie di tentativi di code di spostare manualmente i messaggi tra le code dei tentativi e le principali coda di elaborazione basato su una serie di timer e alcune euristiche, solo l'uso di materie prime di Sistema.Di messaggistica di roba per gestire le code MSMQ.Sembra funzionare abbastanza bene, anche se ci sono un paio di trucchi se si va in questo modo.

Altri suggerimenti

Penso che con MSMQ (disponibile solo su Vista), potreste essere in grado di fare come questo:

<bindings>
    <netMsmqBinding>
        <binding name="PosionMessageHandling"
             receiveRetryCount="3"
             retryCycleDelay="00:05:00"
             maxRetryCycles="3"
             receiveErrorHandling="Move" />
    </netMsmqBinding>
</bindings>

WCF immediatamente tentativi per ReceiveRetryCount volte dopo il primo errore di chiamata.Dopo che il lotto non è riuscito il messaggio viene spostato a riprova di coda.Dopo un ritardo di RetryCycleDelay minuti, il messaggio spostato dalla coda tentativi di coda dell'endpoint e il batch viene ripetuta.Questa operazione deve essere ripetuta MaxRetryCycle tempo.Se tutto ciò che non funziona il messaggio viene gestito secondo receiveErrorHandling che si possono spostare (a veleno di coda), di rifiutare, di caduta o di guasto

Un buon testo su WCF e MSMQ è il chapther 9 di Progammig WCF libro Juval Lowy

Se si utilizza SQL-Server, allora si dovrebbe utilizzare una transazione distribuita, dal momento che entrambi MSMQ e SQL-Server la supporta.Quello che succede è di avvolgere il vostro database di scrivere in un TransactionScope blocco e chiamare ambito.Completa() solo se l'esito è positivo.Se non si riesce, poi quando il tuo WCF metodo restituisce il messaggio verrà inserito in coda per essere provato di nuovo.Ecco una tagliato versione del codice che uso:

    [OperationBehavior(TransactionScopeRequired=true, TransactionAutoComplete=true)]
    public void InsertRecord(RecordType record)
    {
        try
        {
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
            {
                SqlConnection InsertConnection = new SqlConnection(ConnectionString);
                InsertConnection.Open();

                // Insert statements go here

                InsertConnection.Close();

                // Vote to commit the transaction if there were no failures
                scope.Complete();
            }
        }
        catch (Exception ex)
        {
            logger.WarnException(string.Format("Distributed transaction failure for {0}", 
                Transaction.Current.TransactionInformation.DistributedIdentifier.ToString()),
                ex);
        }
     }

Ho da fare la coda un grande, ma si conosce il numero di record, lasciate WCF avviare un sacco di thread per gestire molti di loro contemporaneamente (raggiunge il 16 thread--16 messaggi off coda alla volta), poi uccidere il processo nel mezzo di operazioni.Quando il programma viene riavviato i messaggi vengono letti coda e trasformati di nuovo come se nulla fosse successo, e, a conclusione della prova il database è coerente e non ha alcun record mancanti.

Il Distributed Transaction Manager è un ambiente di presenza, e quando si crea una nuova istanza di TransactionScope cerca automaticamente per la transazione corrente nell'ambito del metodo invokation-che dovrebbe essere stato creato già da WCF quando è spuntato il messaggio della coda e invocato il metodo.

Purtroppo mi sono bloccato su Windows XP e Windows Server 2003 in modo che non è un'opzione per me.- (Ho ri-precisare che nella mia domanda ho trovato questa soluzione dopo la pubblicazione e mi sono reso conto che potevo usarla)

Ho trovato che una soluzione è l'installazione di un gestore personalizzato che vorresti spostare il mio messaggio su un'altra coda o coda di veleno e riavviare il servizio.Questo mi sembrava da pazzi.Immaginate la mia Sql Server era giù come spesso il servizio sarebbe stato riavviato.

COSÌ quello che ho finito per fare è permettere la Linea di colpa e lasciare messaggi nella coda.Anche io registro un fatale del messaggio al mio sistema di servizio di registrazione di ciò che è accaduto.Una volta che il nostro problema è stato risolto, ho riavviato il servizio e tutti i messaggi di avviare l'elaborazione di nuovo.

Ho capito ri-elaborazione del messaggio o qualsiasi altro fallirà, perché la necessità di spostare questo messaggio e gli altri in un'altra coda.Non interrompere il mio servizio, e iniziare di nuovo quando tutto funziona come previsto.

aogan, hai avuto la risposta perfetta per MSMQ 4.0, ma purtroppo non per me

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top