Delen via


Afhandeling van gifberichten

Een gifbericht is een bericht dat het maximum aantal bezorgingspogingen naar de toepassing heeft overschreden. Deze situatie kan zich voordoen wanneer een toepassing op basis van een wachtrij een bericht niet kan verwerken vanwege fouten. Om te voldoen aan de betrouwbaarheidsvereisten, ontvangt een toepassing in de wachtrij berichten onder een transactie. Als u de transactie waarin een bericht in de wachtrij is geplaatst, afgebroken, blijft het bericht in de wachtrij staan, zodat het bericht opnieuw wordt geprobeerd onder een nieuwe transactie. Als het probleem waardoor de transactie is afgebroken niet wordt gecorrigeerd, kan de ontvangende toepassing vastlopen in een lus die hetzelfde bericht ontvangt en afbreekt totdat het maximum aantal bezorgingspogingen is overschreden en er een gifbericht wordt weergegeven.

Een bericht kan om vele redenen een gifbericht worden. De meest voorkomende redenen zijn toepassingsspecifiek. Als een toepassing bijvoorbeeld een bericht uit een wachtrij leest en een bepaalde databaseverwerking uitvoert, kan de toepassing geen vergrendeling op de database krijgen, waardoor de transactie wordt afgebroken. Omdat de databasetransactie is afgebroken, blijft het bericht in de wachtrij, waardoor de toepassing het bericht een tweede keer opnieuw kan lezen en een andere poging doet om een vergrendeling op de database te verkrijgen. Berichten kunnen ook gif worden als ze ongeldige informatie bevatten. Een inkooporder kan bijvoorbeeld een ongeldig klantnummer bevatten. In deze gevallen kan de aanvraag de transactie vrijwillig afbreken en het bericht dwingen om een gifbericht te worden.

In zeldzame gevallen kunnen berichten niet naar de toepassing worden verzonden. De WCF-laag (Windows Communication Foundation) kan een probleem met het bericht vinden, bijvoorbeeld als het bericht het verkeerde frame heeft, ongeldige berichtreferenties eraan zijn gekoppeld of een ongeldige actiekoptekst. In dergelijke gevallen ontvangt de toepassing het bericht nooit; het bericht kan echter nog steeds een gifbericht worden en handmatig worden verwerkt.

Gifberichten verwerken

In WCF biedt de verwerking van gifberichten een mechanisme voor een ontvangende toepassing voor het verwerken van berichten die niet kunnen worden verzonden naar de toepassing of berichten die naar de toepassing worden verzonden, maar die niet kunnen worden verwerkt vanwege toepassingsspecifieke redenen. Configureer de verwerking van gifberichten met de volgende eigenschappen in elk van de beschikbare in de wachtrij geplaatste bindingen:

  • ReceiveRetryCount. Een geheel getal dat het maximum aantal keren aangeeft dat een bericht uit de toepassingswachtrij opnieuw moet worden bezorgd. De standaardwaarde is 5. Dit is voldoende in gevallen waarin een onmiddellijke nieuwe poging het probleem oplost, zoals met een tijdelijke impasse in een database.

  • MaxRetryCycles. Een geheel getal dat het maximum aantal nieuwe pogingen aangeeft. Een cyclus voor opnieuw proberen bestaat uit het overbrengen van een bericht uit de toepassingswachtrij naar de submap voor opnieuw proberen en, na een configureerbare vertraging, van de subqueemping opnieuw proberen naar de toepassingswachtrij om de bezorging opnieuw te beperken. De standaardwaarde is 2. Op Windows Vista wordt het bericht maximaal (ReceiveRetryCount +1) * (MaxRetryCycles + 1) keer geprobeerd. MaxRetryCycles wordt genegeerd op Windows Server 2003 en Windows XP.

  • RetryCycleDelay. De tijdsvertraging tussen nieuwe pogingen. De standaardwaarde is 30 minuten. MaxRetryCycles en RetryCycleDelay samen een mechanisme bieden voor het oplossen van het probleem waarbij een nieuwe poging na een periodieke vertraging het probleem oplost. Dit verwerkt bijvoorbeeld een vergrendelde rijset in SQL Server in afwachting van transactiedoorvoering.

  • ReceiveErrorHandling. Een opsomming die aangeeft welke actie moet worden ondernomen voor een bericht dat is mislukt nadat het maximum aantal nieuwe pogingen is geprobeerd. De waarden kunnen fout, neerzetten, negeren en verplaatsen zijn. De standaardoptie is Fout.

  • Schuld. Met deze optie wordt een fout verzonden naar de listener die de ServiceHost fout heeft veroorzaakt. Het bericht moet door een extern mechanisme uit de toepassingswachtrij worden verwijderd voordat de toepassing berichten uit de wachtrij kan blijven verwerken.

  • Drop. Deze optie laat het gifbericht vallen en het bericht wordt nooit bezorgd bij de toepassing. Als de eigenschap van TimeToLive het bericht op dit moment is verlopen, kan het bericht worden weergegeven in de wachtrij voor dode brieven van de afzender. Als dat niet het geval is, wordt het bericht nergens weergegeven. Met deze optie wordt aangegeven dat de gebruiker niet heeft opgegeven wat u moet doen als het bericht verloren gaat.

  • Verwerpen. Deze optie is alleen beschikbaar op Windows Vista. Hierdoor wordt Message Queuing (MSMQ) geïnstrueerd om een negatieve bevestiging terug te sturen naar de berichtenwachtrijbeheerder die de toepassing het bericht niet kan ontvangen. Het bericht wordt geplaatst in de wachtrij voor het verzenden van wachtrijbeheer.

  • Verplaatsen. Deze optie is alleen beschikbaar op Windows Vista. Hiermee wordt het gifbericht verplaatst naar een gif-berichtenwachtrij voor latere verwerking door een toepassing voor het verwerken van gifberichten. De gifberichtwachtrij is een subquee van de toepassingswachtrij. Een toepassing voor de verwerking van gifberichten kan een WCF-service zijn waarmee berichten uit de gifwachtrij worden gelezen. De gifwachtrij is een subqueue van de toepassingswachtrij en kan worden aangepakt als net.msmq://<machine-name>/applicationQueue; gif, waarbij machinenaam de naam is van de computer waarop de wachtrij zich bevindt en de applicationQueue de naam is van de toepassingsspecifieke wachtrij.

Hieronder ziet u het maximum aantal bezorgingspogingen voor een bericht:

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

  • (ReceiveRetryCount + 1) op Windows Server 2003 en Windows XP.

Notitie

Er worden geen nieuwe pogingen gedaan voor een bericht dat is bezorgd.

Als u het aantal keren wilt bijhouden dat een bericht wordt gelezen, behoudt Windows Vista een duurzame berichteigenschap waarmee het aantal afgebroken berichten wordt geteld en een eigenschap voor het aantal verplaatsingen waarmee het aantal keren wordt geteld dat het bericht wordt verplaatst tussen de wachtrij van de toepassing en subqueues. Het WCF-kanaal gebruikt deze om het aantal nieuwe pogingen en het aantal nieuwe pogingen te berekenen. Op Windows Server 2003 en Windows XP wordt het aantal afbreken in het geheugen onderhouden door het WCF-kanaal en wordt het opnieuw ingesteld als de toepassing mislukt. Het WCF-kanaal kan ook het aantal afgebroken berichten op elk gewenst moment in het geheugen bevatten. Als een 257e bericht wordt gelezen, wordt het aantal afgebroken berichten van het oudste bericht opnieuw ingesteld.

De eigenschappen voor het afbreken en aantal verplaatsingen zijn beschikbaar voor de servicebewerking via de bewerkingscontext. In het volgende codevoorbeeld ziet u hoe u deze kunt openen.

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 biedt twee standaardbindingen in de wachtrij:

  • NetMsmqBinding. Een .NET Framework-binding die geschikt is voor het uitvoeren van communicatie op basis van wachtrijen met andere WCF-eindpunten.

  • MsmqIntegrationBinding. Een binding die geschikt is voor communicatie met bestaande Message Queuing-toepassingen.

Notitie

U kunt eigenschappen in deze bindingen wijzigen op basis van de vereisten van uw WCF-service. Het volledige mechanisme voor het verwerken van gifberichten is lokaal voor de ontvangende toepassing. Het proces is onzichtbaar voor de verzendende toepassing, tenzij de ontvangende toepassing uiteindelijk stopt en een negatieve bevestiging naar de afzender verzendt. In dat geval wordt het bericht verplaatst naar de wachtrij met dode letters van de afzender.

Best Practice: MsmqPoisonMessageException verwerken

Wanneer de service bepaalt dat een bericht gif is, gooit het transport in de wachtrij een MsmqPoisonMessageException die het LookupId gifbericht bevat.

Een ontvangende toepassing kan de IErrorHandler interface implementeren om eventuele fouten te verwerken die de toepassing nodig heeft. Zie Uitbreiding van controle over foutafhandeling en rapportage voor meer informatie.

De toepassing kan een soort geautomatiseerde verwerking van gifberichten vereisen die de gifberichten naar een gifberichtwachtrij verplaatsen, zodat de service toegang heeft tot de rest van de berichten in de wachtrij. Het enige scenario voor het gebruik van het mechanisme voor fout-handler om te luisteren naar uitzonderingen voor gifberichten is wanneer de ReceiveErrorHandling instelling is ingesteld op Fault. Het gifberichtvoorbeeld voor Message Queuing 3.0 laat dit gedrag zien. Hieronder vindt u een overzicht van de stappen die moeten worden uitgevoerd voor het afhandelen van gifberichten, waaronder aanbevolen procedures:

  1. Zorg ervoor dat uw gifinstellingen overeenkomen met de vereisten van uw toepassing. Wanneer u met de instellingen werkt, moet u ervoor zorgen dat u de verschillen begrijpt tussen de mogelijkheden van Message Queuing op Windows Vista, Windows Server 2003 en Windows XP.

  2. Implementeer zo nodig de IErrorHandler fout voor het afhandelen van gifberichten. Omdat voor het instellen ReceiveErrorHandlingFault een handmatig mechanisme is vereist om het gifbericht uit de wachtrij te verplaatsen of om een extern afhankelijk probleem te corrigeren, moet het gebruikelijke gebruik worden geïmplementeerd IErrorHandler wanneer ReceiveErrorHandling deze is ingesteld Faultop , zoals wordt weergegeven in de volgende code.

    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 wire…not 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. Maak een PoisonBehaviorAttribute servicegedrag dat kan worden gebruikt. Het gedrag installeert het IErrorHandler op de dispatcher. Zie het volgende codevoorbeeld.

    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. Zorg ervoor dat uw service is geannoteerd met het kenmerk gifgedrag.

Bovendien, als de ReceiveErrorHandling is ingesteld op Fault, de ServiceHost fouten bij het tegenkomen van het gifbericht. U kunt koppelen aan de foutieve gebeurtenis en de service afsluiten, corrigerende acties ondernemen en opnieuw opstarten. U kunt bijvoorbeeld de LookupId API MsmqPoisonMessageExceptionIErrorHandler gebruiken om het bericht uit de wachtrij te ontvangen en wanneer de servicehostfouten optreden, kunt u de System.Messaging API gebruiken om het bericht uit de wachtrij te ontvangen met behulp van het LookupId bericht uit de wachtrij te verwijderen en het bericht op te slaan in een externe winkel of een andere wachtrij. Vervolgens kunt u opnieuw opstarten ServiceHost om de normale verwerking te hervatten. De afhandeling van gifberichten in MSMQ 4.0 laat dit gedrag zien.

Time-out van transacties en gifberichten

Er kan een klasse fouten optreden tussen het transportkanaal in de wachtrij en de gebruikerscode. Deze fouten kunnen worden gedetecteerd door lagen tussen de lagen, zoals de beveiligingslaag voor berichten of de logica voor het verzenden van services. Een ontbrekend X.509-certificaat dat is gedetecteerd in de SOAP-beveiligingslaag en een ontbrekende actie zijn bijvoorbeeld gevallen waarin het bericht wordt verzonden naar de toepassing. Als dit gebeurt, wordt het bericht door het servicemodel wegvalt. Omdat het bericht wordt gelezen in een transactie en een resultaat voor die transactie niet kan worden opgegeven, treedt er uiteindelijk een time-out op, wordt de transactie afgebroken en wordt het bericht weer in de wachtrij geplaatst. Met andere woorden, voor een bepaalde klasse fouten wordt de transactie niet onmiddellijk afgebroken, maar wordt gewacht totdat er een time-out optreedt voor de transactie. U kunt de time-out voor transacties voor een service wijzigen met behulp van ServiceBehaviorAttribute.

Als u de time-out van de transactie op computerbrede basis wilt wijzigen, wijzigt u het bestand machine.config en stelt u de juiste time-out voor de transactie in. Het is belangrijk om te weten dat, afhankelijk van de time-out die is ingesteld in de transactie, de transactie uiteindelijk wordt afgebroken en teruggaat naar de wachtrij en het afgebroken aantal wordt verhoogd. Uiteindelijk wordt het bericht vergiftigd en wordt de juiste verwijdering gemaakt volgens de gebruikersinstellingen.

Sessies en gifberichten

Een sessie ondergaat dezelfde procedures voor opnieuw proberen en vergiftigingsberichten als één bericht. De eerder vermelde eigenschappen voor gifberichten zijn van toepassing op de hele sessie. Dit betekent dat de hele sessie opnieuw wordt geprobeerd en naar een uiteindelijke gifberichtwachtrij of de wachtrij met dode brieven van de afzender gaat als het bericht wordt geweigerd.

Berichten in batchverwerking en gif

Als een bericht een gifbericht wordt en deel uitmaakt van een batch, wordt de hele batch teruggedraaid en wordt het kanaal teruggedraaid om één bericht tegelijk te lezen. Zie Berichten in batchverwerking in een transactie voor meer informatie over batchverwerking

Afhandeling van gifberichten voor berichten in een gifwachtrij

De verwerking van gifberichten eindigt niet wanneer een bericht in de wachtrij voor gifberichten wordt geplaatst. Berichten in de wachtrij voor gifberichten moeten nog steeds worden gelezen en verwerkt. U kunt een subset van de instellingen voor de verwerking van gifberichten gebruiken bij het lezen van berichten uit de uiteindelijke gif-subquee. De toepasselijke instellingen zijn ReceiveRetryCount en ReceiveErrorHandling. U kunt instellen ReceiveErrorHandling op Neerzetten, Weigeren of Fout. MaxRetryCycles wordt genegeerd en er wordt een uitzondering gegenereerd als ReceiveErrorHandling deze is ingesteld op Verplaatsen.

Verschillen tussen Windows Vista, Windows Server 2003 en Windows XP

Zoals eerder vermeld, zijn niet alle instellingen voor de verwerking van gifberichten van toepassing op Windows Server 2003 en Windows XP. De volgende belangrijke verschillen tussen Message Queuing op Windows Server 2003, Windows XP en Windows Vista zijn relevant voor de verwerking van gifberichten:

  • Message Queuing in Windows Vista ondersteunt subqueues, terwijl Windows Server 2003 en Windows XP geen subqueues ondersteunen. Subqueues worden gebruikt bij het verwerken van gifberichten. De wachtrijen voor opnieuw proberen en de gifwachtrij zijn subqueeën voor de toepassingswachtrij die is gemaakt op basis van de instellingen voor het afhandelen van gifberichten. De MaxRetryCycles dicteert hoeveel nieuwe pogingen moeten worden gemaakt. Daarom worden bij uitvoering op Windows Server 2003 of Windows XP MaxRetryCycles genegeerd en ReceiveErrorHandling.Move is het niet toegestaan.

  • Message Queuing in Windows Vista ondersteunt negatieve bevestiging, terwijl Windows Server 2003 en Windows XP dat niet doen. Een negatieve bevestiging van de ontvangende wachtrijbeheerder zorgt ervoor dat de verzendende wachtrijbeheerder het geweigerde bericht in de wachtrij met dode letters plaatst. ReceiveErrorHandling.Reject Daarom is het niet toegestaan met Windows Server 2003 en Windows XP.

  • Message Queuing in Windows Vista ondersteunt een berichteigenschap die het aantal keren dat de bezorging van berichten wordt uitgevoerd, wordt bijgehouden. Deze eigenschap voor afgebroken aantal is niet beschikbaar in Windows Server 2003 en Windows XP. WCF onderhoudt het afgebroken aantal in het geheugen, dus het is mogelijk dat deze eigenschap geen nauwkeurige waarde bevat wanneer hetzelfde bericht wordt gelezen door meer dan één WCF-service in een farm.

Zie ook