Freigeben über


Behandlung nicht verarbeitbarer Nachrichten

Eine nicht verarbeitbare Nachricht ist eine Nachricht, die auch nach der maximalen Anzahl von Zustellversuchen nicht an die Anwendung ausgeliefert werden konnte. Diese Situation kann auftreten, wenn eine warteschlangenbasierte Anwendung aufgrund der Fehler keine Nachricht verarbeiten kann. Um Zuverlässigkeitsforderungen zu erfüllen, empfängt eine in der Warteschlange stehende Anwendung Nachrichten unter einer Transaktion. Beim Abbrechen der Transaktion, in der eine in der Warteschlange stehende Nachricht empfangen wurde, bleibt die Nachricht in der Warteschlange und wird dann unter einer neuen Transaktion wiederholt. Wenn das Problem, das zum Abbrechen der Transaktion geführt hat, nicht korrigiert wird, kann die empfangende Anwendung in einer Schleife hängen bleiben, in der sie dieselbe Nachricht immer wieder empfängt und abbricht, bis die maximale Anzahl der Zustellversuche überschritten ist. Auf diese Weise entsteht eine nicht verarbeitbare Nachricht.

Eine Nachricht kann aus vielen Gründen zu einer nicht verarbeitbaren Nachrichten werden. Die häufigsten Ursachen sind anwendungsspezifisch. Wenn beispielsweise eine Anwendung eine Nachricht aus einer Warteschlange liest und dann Datenbankprozesse durchführt, kann es vorkommen, dass von der Anwendung keine Sperre für die Datenbank bewirkt werden kann. Dies führt dann dazu, dass sie die Transaktion abbricht. Da die Datenbanktransaktion abgebrochen wurde, verbleibt die Nachricht in der Warteschlange, wodurch die Nachricht von der Anwendung ein zweites Mal gelesen und ein neuer Versuch gestartet wird, eine Sperrung der Datenbank zu bewirken. Nachrichten können auch nicht verarbeitbar werden, wenn sie ungültige Informationen enthalten. So enthält z. B. eine Bestellung möglicherweise eine ungültige Kundennummer. In diesen Fällen kann die Anwendung die Transaktion freiwillig abbrechen und die Nachricht zwingen, eine nicht verarbeitbare Nachricht zu werden.

Bei seltenen Gelegenheiten können Nachrichten nicht zur Anwendung weitergeleitet werden. Die Windows Communication Foundation (WCF)-Schicht kann ein Problem mit der Nachricht feststellen, beispielsweise wenn die Nachricht den falschen Frame, ungültige Nachrichtenanmeldeinformationen im Anhang oder einen ungültigen Aktionsheader aufweist. In diesen Fällen empfängt die Anwendung die Nachricht niemals; trotzdem kann die Nachricht noch zu einer nicht verarbeitbaren Nachricht werden, die manuell verarbeitet werden kann.

Behandeln von nicht verarbeitbaren Nachrichten

In WCF bietet die Behandlung nicht verarbeitbarer Nachrichten einen Mechanismus, mit dem eine empfangende Anwendung mit Nachrichten umgehen kann, die nicht zur Anwendung weitergeleitet werden können, oder mit Nachrichten, die zwar zur Anwendung weitergeleitet werden, deren Verarbeitung jedoch aus anwendungsspezifischen Gründen fehlschlägt. Die Konfiguration der Behandlung nicht verarbeitbarer Nachrichten erfolgt in jeder der verfügbaren, in der Warteschlange stehenden Bindungen durch die folgenden Eigenschaften:

  • ReceiveRetryCount. Ein Ganzzahlwert, die die maximale Anzahl der Neuversuche für den Versand einer Nachricht von der Anwendungswarteschlange zu der Anwendung angibt. Der Standardwert ist 5. Dieser Wert ist in Fällen ausreichend, in denen eine sofortige Wiederholung das Problem behebt, beispielsweise wenn ein temporärer Deadlock für eine Datenbank vorliegt.

  • MaxRetryCycles. Ein Ganzzahlwert, der die maximale Anzahl der Wiederholungszyklen angibt. Ein Wiederholungszyklus umfasst die Übertragung einer Nachricht von der Anwendungswarteschlange zur untergeordneten Wiederholungswarteschlange und – nach einer konfigurierbaren Verzögerung – die Rückübertragung der Nachricht aus der untergeordneten Wiederholungswarteschlange zur Anwendungswarteschlange, um einen erneuten Zustellversuch zu unternehmen. Der Standardwert ist 2. In Windows Vista erfolgen maximal (ReceiveRetryCount +1) * (MaxRetryCycles + 1) Versuche. MaxRetryCycles wird in Windows Server 2003 und Windows XP ignoriert.

  • RetryCycleDelay. Die Verzögerungszeit für Wiederholungszyklen. Der Standardwert ist 30 Minuten. MaxRetryCycles und RetryCycleDelay bieten gemeinsam einen Mechanismus zur Behandlung des Problems, wenn eine Wiederholung nach einer periodischen Verzögerung das Problem behebt. Damit wird z. B. ein gesperrtes Rowset bei einem in SQL Server anstehenden Transaktionscommit behandelt.

  • ReceiveErrorHandling. Eine Enumeration, die angibt, welche Aktion für eine Nachricht erfolgen soll, deren Zustellung auch nach der maximalen Anzahl von Wiederholungen fehlgeschlagen ist. Die Werte können "Fehler", "Ablage", "Ablehnen" und "Verschieben" sein. Die Standardoption ist "Fehler".

  • Fehler. Diese Option sendet einen Fehler an den Listener, der bewirkt hat, dass der ServiceHost fehlerhaft agiert. Die Nachricht muss durch einen externen Mechanismus aus der Anwendungswarteschlange entfernt werden, bevor die Anwendung mit der Verarbeitung von Nachrichten aus der Warteschlange fortfahren kann.

  • Ablage. Diese Option legt die nicht verarbeitbare Nachricht ab, und die Nachricht wird der Anwendung nie zugestellt. Wenn die Eigenschaft TimeToLive der Nachricht zu diesem Zeitpunkt bereits abgelaufen ist, kann die Nachricht in der Warteschlange für unzustellbare Nachrichten des Absenders angezeigt werden. Andernfalls wird die Nachricht nirgendwo angezeigt. Diese Option gibt an, dass vom Benutzer keine Aktion für den Fall angegeben wurde, dass die Nachricht verloren geht.

  • Ablehnen. Diese Option ist nur in Windows Vista verfügbar. Damit wird das Message Queuing (MSMQ) angewiesen, eine negative Bestätigung mit dem Hinweis, dass die Anwendung die Nachricht nicht empfangen kann, an den sendenden Warteschlangen-Manager zu senden. Die Nachricht wird in die Warteschlange für unzustellbare Nachrichten des sendenden Warteschlangen-Managers eingefügt.

  • Verschieben. Diese Option ist nur in Windows Vista verfügbar. Damit wird die nicht verarbeitbare Nachricht in eine Warteschlange für potenziell schädliche Nachrichten verschoben, sodass sie später durch eine Anwendung zur Behandlung nicht verarbeitbarer Nachrichten verarbeitet werden kann. Die Warteschlange für potenziell schädliche Nachrichten ist eine untergeordnete Warteschlange der Anwendungswarteschlange. Eine Anwendung für nicht verarbeitbare Nachrichten kann ein WCF-Dienst sein, der Nachrichten aus der Warteschlange für potenziell schädliche Nachrichten liest. Die Warteschlange für potenziell schädliche Nachrichten ist eine untergeordnete Warteschlange der Anwendungswarteschlange und kann als net.msmq://<machine-name>/applicationQueue;poison adressiert werden, wobei machine-name der Name des Computers ist, auf dem sich die Warteschlange befindet, und applicationQueue der Name der anwendungsspezifischen Warteschlange.

Im Folgenden ist die maximale Anzahl von für eine Nachricht durchgeführten Übermittlungsversuchen dargestellt:

  • ((ReceiveRetryCount+1) * (MaxRetryCycles + 1)) auf Windows Vista.

  • (ReceiveRetryCount+1) auf Windows Server 2003 und Windows XP.

ms789028.note(de-de,VS.100).gifHinweis:
Für eine Nachricht, die erfolgreich zugestellt wird, werden keine Wiederholungen durchgeführt.

Zur Nachverfolgung, wie oft das Lesen einer Nachricht versucht wurde, verfügt Windows Vista über eine dauerhafte Nachrichteneigenschaft, die die Anzahl der Abbrüche zählt, und über eine Verschiebungszähleigenschaft, die zählt, wie oft die Nachricht zwischen der Anwendungswarteschlange und den untergeordneten Warteschlangen verschoben wurde. Der WCF-Kanal verwendet diese Eigenschaften zur Berechnung der Empfangswiederholungsanzahl und der Wiederholungszyklusanzahl. In Windows Server 2003 und Windows XP wird die Abbruchanzahl durch den WCF-Kanal im Arbeitsspeicher geführt und zurückgesetzt, wenn die Anwendung fehlschlägt. Außerdem kann der WCF-Kanal die Abbruchanzahl für bis zu 256 Nachrichten zu jedem beliebigen Zeitpunkt im Arbeitsspeicher führen. Wenn eine 257. Nachricht gelesen wird, dann wird die Abbruchanzahl der ältesten Nachricht zurückgesetzt.

Die Abbruchanzahl- und Verschiebungsanzahleigenschaften stehen dem Dienstvorgang durch den Vorgangskontext zur Verfügung. Im folgenden Codebeispiel wird der Zugriff darauf veranschaulicht.

MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine("Abort count: {0} ", mqProp.AbortCount);
Console.WriteLine("Move count: {0} ", mqProp.MoveCount);
// code to submit purchase order ...

WCF stellt zwei in der Warteschlange stehende Standardbindungen bereit:

  • NetMsmqBinding. Eine .NET Framework-Bindung, die zum Ausführen warteschlangenbasierter Kommunikation mit anderen WCF-Endpunkten geeignet ist.

  • MsmqIntegrationBinding. Eine Bindung, die zur Kommunikation mit vorhandenen Message Queuing-Anwendungen geeignet ist.

ms789028.note(de-de,VS.100).gifHinweis:
Sie können Eigenschaften in diesen Bindungen auf der Grundlage der Anforderungen Ihres WCF-Diensts ändern. Der gesamte Mechanismus zur Behandlung nicht verarbeitbarer Nachrichten ist zur empfangenden Anwendung lokal. Der Prozess ist für die sendende Anwendung unsichtbar, es sei denn, die empfangende Anwendung beendet den Vorgang und sendet eine negative Bestätigung an den Absender zurück. In diesem Fall wird die Nachricht in die Warteschlange für unzustellbare Nachrichten des Absenders verschoben.

Empfohlene Vorgehensweise: Behandlung MsmqPoisonMessageException

Wenn der Dienst feststellt, dass eine Nachricht nicht verarbeitbar ist, löst der Warteschlangentransport eine MsmqPoisonMessageException aus, die die LookupId der nicht verarbeitbaren Nachricht enthält.

Eine empfangende Anwendung kann die IErrorHandler-Schnittstelle implementieren, um alle Fehler zu behandeln, die die Anwendung erfordert. Weitere Informationen finden Sie unter Erweitern der Kontrolle über Fehlerbehandlung und -meldung.

Die Anwendung erfordert möglicherweise eine bestimmte automatische Behandlung von nicht verarbeitbaren Nachrichten, mit der die nicht verarbeitbaren Nachrichten in eine entsprechende Warteschlange verschoben werden, sodass der Dienst auf die restlichen Nachrichten in der Warteschlange zugreifen kann. Das einzige Szenario, in dem der Fehlerbehandlungsmechanismus zum Abhören auf Ausnahmen für nicht verarbeitbare Nachrichten verwendet werden kann, liegt vor, wenn die ReceiveErrorHandling-Einstellung auf Fault festgelegt ist. Das Beispiel der nicht verarbeitbaren Nachricht für Message Queuing 3.0 veranschaulicht dieses Verhalten. Im Folgenden werden die Schritte zur Behandlung nicht verarbeitbarer Nachrichten, einschließlich empfohlener Vorgehensweisen, umrissen:

  1. Stellen Sie sicher, dass die Einstellungen für nicht verarbeitbare Nachrichten den Anforderungen Ihrer Anwendung entsprechen. Stellen Sie bei der Arbeit mit diesen Einstellungen sicher, dass Ihnen die Unterschiede zwischen den Message Queuing-Fähigkeiten in Windows Vista, Windows Server 2003 und Windows XP bekannt sind.

  2. Implementieren Sie falls erforderlich den IErrorHandler, um Fehler mit nicht verarbeitbaren Nachrichten zu behandeln. Das das Festlegen von ReceiveErrorHandling auf Fault einen manuellen Mechanismus zum Verschieben der nicht verarbeitbaren Nachricht aus der Warteschlange oder zum Korrigieren eines Problems mit externen Abhängigkeiten erfordert, besteht die typische Nutzung darin, den IErrorHandler zu implementieren, wenn ReceiveErrorHandling auf Fault festgelegt ist, wie im folgenden Code gezeigt:

    class PoisonErrorHandler : IErrorHandler
    {
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // No-op -We are not interested in this. This is only useful if you want to send back a fault on the wirenot applicable for queues [one-way].
        }
    
        public bool HandleError(Exception error)
        {
            if (error != null && error.GetType() == typeof(MsmqPoisonMessageException))
            {
                Console.WriteLine(" Poisoned message -message look up id = {0}", ((MsmqPoisonMessageException)error).MessageLookupId);
                return true;
            }
    
            return false;
        }
    }
    
  3. Erstellen Sie ein PoisonBehaviorAttribute, das das Dienstverhalten verwenden kann. Das Verhalten installiert den IErrorHandler auf dem Verteiler. Siehe nachstehendes Codebeispiel.

    public class PoisonErrorBehaviorAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;
    
        public PoisonErrorBehaviorAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }
    
        void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }
    
        void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
        {
        }
    
        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
    
            try
            {
                errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            }
            catch (MissingMethodException e)
            {
                throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must have a public empty constructor", e);
            }
            catch (InvalidCastException e)
            {
                throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler", e);
            }
    
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }
    
  4. Stellen Sie sicher, dass der Dienst mit dem Verhaltensattribut für nicht verarbeitbare Nachrichten kommentiert wird.

    <configuration>
      <appSettings>
        <!-- use appSetting to configure MSMQ queue name -->
        <add key="queueName" value=".\private$\ServiceModelSamplesPoison" />
        <add key="baseAddress" value="https://localhost:8000/orderProcessor/poisonSample"/>
      </appSettings>
      <system.serviceModel>
        <services>
          <service 
                  name="Microsoft.ServiceModel.Samples.OrderProcessorService">
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison"
                      binding="netMsmqBinding"
                      bindingConfiguration="PoisonBinding" 
                      contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
          </service>
        </services>
    
        <bindings>
          <netMsmqBinding>
            <binding name="PoisonBinding" 
                     receiveRetryCount="0"
                     maxRetryCycles="1"
                     retryCycleDelay="00:00:05"                      
                     receiveErrorHandling="Fault"
                            />
          </netMsmqBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
    

Wenn außerdem das ReceiveErrorHandling auf Fault festgelegt ist, tritt beim ServiceHost ein Fehler auf, wenn dieser auf die nicht verarbeitbare Nachricht stößt. Sie können sich dem Fehlerereignis zuwenden und den Dienst herunterfahren, Gegenmaßnahmen treffen und neu starten. Beispielsweise kann die LookupId in der MsmqPoisonMessageException, die an den IErrorHandler weitergegeben wurde, notiert werden. Tritt nun beim Diensthost ein Fehler auf, können Sie die System.Messaging-API verwenden, um die Nachricht mithilfe der LookupId aus der Warteschlange zu empfangen, die Nachricht aus der Warteschlange zu entfernen und die Nachricht in einem externen Speicher oder einer anderen Warteschlange zu speichern. Sie können dann den ServiceHost neu starten, um die normale Verarbeitung fortzusetzen. Das Poison Message Handling in MSMQ 3.0 veranschaulicht dieses Verhalten.

Transaktionstimeout und nicht verarbeitbare Nachrichten

Eine Klasse von Fehlern kann zwischen dem Wartenschlangentransportkanal und dem Benutzercode auftreten. Diese Fehler können durch Zwischenschichten erkannt werden, beispielsweise die Nachrichtensicherheitsschicht oder die Dienstverteilungslogik. So stellen beispielsweise ein in der SOAP-Sicherheitsschicht erkanntes fehlendes X.509-Zertifikat und eine fehlende Aktion Fälle dar, in denen die Nachricht nicht an die Anwendung verteilt wird. In diesem Fall wird die Nachricht durch das Dienstmodell wieder abgelegt. Da die Nachricht in einer Transaktion gelesen wird und ein Ergebnis für diese Transaktion nicht geliefert werden kann, kommt es letztlich zum Timeout der Transaktion, sie wird abgebrochen, und die Nachricht wird wieder in die Warteschlange zurückgestellt. Mit anderen Worten: Für eine bestimmte Fehlerklasse führt die Transaktion keinen sofortigen Abbruch durch, sondern wartet, bis es zum Timeout der Transaktion kommt. Sie können das Transaktionstimeout für einen Dienst mit ServiceBehaviorAttribute ändern.

Um das Transaktionstimeout auf einer computerweiten Basis zu ändern, modifizieren Sie die machine.config-Datei und legen das entsprechende Transaktionstimeout fest. Wichtig: Die Transaktion wird in Abhängigkeit vom festgelegten Transaktionstimeout schließlich abgebrochen, wieder in der Warteschlange platziert, und die Abbruchanzahl wird erhöht. Schließlich wird die Nachricht nicht verarbeitbar, und die richtige Disposition wird entsprechend den Benutzereinstellungen gewählt.

Sitzungen und nicht verarbeitbare Nachrichten

Eine Sitzung durchläuft die gleichen Wiederholungsprozeduren und Prozeduren zur Behandlung nicht verarbeitbarer Nachrichten wie eine einzelne Nachricht. Die zuvor aufgeführten Eigenschaften für nicht verarbeitbare Nachrichten gelten auch für die ganze Sitzung, d. h., dass die gesamte Sitzung wiederholt wird und schließlich in einer Warteschlange für potenziell schädliche Nachrichten oder in der Absenderwarteschlange für unzustellbare Nachrichten platziert wird, wenn die Nachricht abgelehnt wird.

Batchverarbeitung und nicht verarbeitbare Nachrichten

Wird eine Nachricht zu einer nicht verarbeitbaren Nachricht und ist Teil eines Batches, dann wird für den gesamten Batch ein Rollback durchgeführt, und der Kanal kehrt zum Lesen einzelner Nachrichten zurück. Weitere Informationen über zur Batchverarbeitung finden Sie unter Batchverarbeitung von Nachrichten in einer Transaktion

Behandlung nicht verarbeitbarer Nachrichten für Nachrichten in einer Warteschlange für potenziell schädliche Nachrichten

Die Behandlung nicht verarbeitbarer Nachrichten ist nicht damit beendet, dass eine Nachricht in die Warteschlange für potenziell schädliche Nachrichten eingefügt wird. Die Nachrichten in der Warteschlange für potenziell schädliche Nachrichten müssen immer noch gelesen und behandelt werden. Beim Lesen von Nachrichten aus der endgültigen Warteschlange für potenziell schädliche Nachrichten können Sie eine Teilmenge der Einstellungen zur Behandlung nicht verarbeitbarer Nachrichten verwenden. Die anwendbaren Einstellungen sind ReceiveRetryCount und ReceiveErrorHandling. Sie können ReceiveErrorHandling auf "Ablage", "Ablehnen" oder "Fehler" einstellen. MaxRetryCycles wird ignoriert, und es wird eine Ausnahme ausgelöst, wenn ReceiveErrorHandling auf "Verschieben" eingestellt wird.

Unterschiede zwischen Windows Vista, Windows Server 2003 und Windows XP

Wie bereits oben erwähnt, sind in Windows Server 2003 und Windows XP nicht alle Einstellungen für die Behandlung nicht verarbeitbarer Nachrichten anwendbar. Die folgenden Hauptunterschiede zwischen dem Message Queuing in Windows Server 2003, Windows XP und Windows Vista sind für die Behandlung nicht verarbeitbarer Nachrichten relevant:

  • Message Queuing in Windows Vista unterstützt untergeordnete Warteschlangen, während Windows Server 2003 und Windows XP keine untergeordneten Warteschlangen unterstützen. Untergeordnete Warteschlangen werden zur Behandlung nicht verarbeitbarer Nachrichten verwendet. Die Wiederholungswarteschlangen und die Warteschlange für potenziell schädliche Nachrichten sind untergeordnete Warteschlangen der Anwendungswarteschlange, die basierend auf den Einstellungen für die Behandlung nicht verarbeitbarer Nachrichten erstellt wird. Die Eigenschaft MaxRetryCycles bestimmt, wie viele untergeordnete Wiederholungwarteschlangen erstellt werden sollen. Deshalb werden bei der Ausführung unter Windows Server 2003 oder unter Windows XP die MaxRetryCycles ignoriert, und ReceiveErrorHandling.Move wird nicht zugelassen.

  • Message Queuing in Windows Vista unterstützt die negative Bestätigung, während Windows Server 2003 und Windows XP dies nicht tun. Eine negative Bestätigung vom empfangenden Warteschlangen-Manager bewirkt, dass der sendende Warteschlangen-Manager die abgelehnte Nachricht in die Warteschlange für unzustellbare Nachrichten einstellt. Damit ist ReceiveErrorHandling.Reject in Windows Server 2003 und Windows XP nicht zulässig.

  • Message Queuing in Windows Vista unterstützt eine Nachrichteneigenschaft, die zählt, wie oft die Nachrichtenzustellung versucht wird. Diese Abbruchanzahleigenschaft ist in Windows Server 2003 und Windows XP nicht verfügbar. WCF führt die Abbruchanzahl im Arbeitsspeicher, weshalb es möglich ist, dass diese Eigenschaft eventuell nicht den akkuraten Wert enthält, wenn dieselbe Nachricht durch mehrere WCF-Dienste in einer Farm gelesen wird.

Siehe auch

Konzepte

Warteschlangenübersicht
Unterschiede zwischen den Warteschlangenfunktionen in Windows Vista, Windows Server 2003 und Windows XP
Angeben und Behandeln von Fehlern in Verträgen und Diensten