Zpracování škodlivých zpráv

Jedovatá zpráva je zpráva , která překročila maximální počet pokusů o doručení do aplikace. Tato situace může nastat, když aplikace založená na frontě nemůže zpracovat zprávu z důvodu chyb. Aby bylo možné splnit požadavky na spolehlivost, aplikace zařazená do fronty přijímá zprávy v rámci transakce. Přerušení transakce, ve které byla přijata zpráva zařazená do fronty, ponechá zprávu ve frontě tak, aby se zpráva opakovat pod novou transakcí. Pokud problém, který způsobil přerušení transakce není opraven, přijímající aplikace se může zaseknout ve smyčce příjmu a přerušit stejnou zprávu, dokud nebude překročen maximální počet pokusů o doručení a výsledky otrávené zprávy.

Zpráva se může stát otrávenou zprávou z mnoha důvodů. Nejběžnější důvody jsou specifické pro aplikaci. Pokud například aplikace načte zprávu z fronty a provede zpracování databáze, aplikace nemusí získat zámek databáze, což způsobí přerušení transakce. Vzhledem k tomu, že došlo k přerušení databázové transakce, zůstane zpráva ve frontě, což způsobí, že aplikace zprávu znovu přečte a provede další pokus o získání zámku v databázi. Zprávy mohou být také otrávené, pokud obsahují neplatné informace. Například nákupní objednávka může obsahovat neplatné číslo zákazníka. V těchto případech může aplikace dobrovolně přerušit transakci a vynutit, aby se zpráva stala otrávenou zprávou.

Ve výjimečných případech může dojít k selhání odeslání zpráv do aplikace. Vrstva WCF (Windows Communication Foundation) může narazit na problém se zprávou, například pokud zpráva obsahuje nesprávný rámec, jsou k ní připojeny neplatné přihlašovací údaje zprávy nebo neplatná hlavička akce. V těchto případech aplikace nikdy neobdrží zprávu; zpráva se však může stále stát otrávenou zprávou a bude zpracována ručně.

Zpracování jedových zpráv

Zpracování otrávených zpráv ve WCF poskytuje mechanismus pro příjem aplikací pro zpracování zpráv, které nelze odeslat do aplikace nebo zpráv odesílaných do aplikace, ale které se nezpracují z důvodů specifických pro danou aplikaci. V každé z dostupných vazeb zařazených do fronty nakonfigurujte zpracování otrávených zpráv s následujícími vlastnostmi:

  • ReceiveRetryCount. Celočíselná hodnota označující maximální počet opakování doručení zprávy z fronty aplikace do aplikace. Výchozí hodnota je 5. To stačí v případech, kdy okamžité opakování vyřeší problém, například dočasné zablokování databáze.

  • MaxRetryCycles. Celočíselná hodnota označující maximální počet cyklů opakování. Cyklus opakování se skládá z přenosu zprávy z fronty aplikace do dílčího fronty opakování a po konfigurovatelné prodlevě z podkateku opakování zpět do fronty aplikace za účelem opětovného spuštění doručení. Výchozí hodnota je 2. Ve Windows Vista se zpráva snaží maximálně (ReceiveRetryCount +1) * (MaxRetryCycles + 1) krát. MaxRetryCycles je ignorován v systémech Windows Server 2003 a Windows XP.

  • RetryCycleDelay. Časové zpoždění mezi cykly opakování. Výchozí hodnota je 30 minut. MaxRetryCycles a RetryCycleDelay společně poskytují mechanismus pro řešení problému, kdy opakování po pravidelném zpoždění problém opraví. To například zpracovává uzamčený řádek nastavený v SQL Serveru čekající na potvrzení transakce.

  • ReceiveErrorHandling. Výčet, který označuje akci, která se má provést pro zprávu, která selhala doručení po pokusu o maximální počet opakovaných pokusů. Hodnoty můžou být Chyba, Drop, Reject a Move. Výchozí možností je Chyba.

  • Chyba. Tato možnost odešle naslouchacímu procesu chybu, která způsobila ServiceHost chybu. Aby aplikace mohl dál zpracovávat zprávy z fronty, je nutné ji z fronty odebrat některým externím mechanismem.

  • Drop. Tato možnost zahodí zprávu a zpráva se nikdy nedoručí do aplikace. Pokud v tuto chvíli vypršela platnost vlastnosti zprávy TimeToLive , může se zpráva zobrazit ve frontě nedoručených zpráv odesílatele. Pokud ne, zpráva se nikde nezobrazí. Tato možnost označuje, že uživatel nezadá, co má dělat, pokud dojde ke ztrátě zprávy.

  • Odmítnout. Tato možnost je k dispozici pouze v systému Windows Vista. To dává pokyn službě Message Queuing (MSMQ), aby odeslal negativní potvrzení zpět správci odesílající fronty, že aplikace nemůže přijmout zprávu. Zpráva se umístí do fronty odesílajícího správce fronty s nedoručenou zprávou.

  • Přesunout. Tato možnost je k dispozici pouze v systému Windows Vista. Tím přesunete otrávenou zprávu do fronty jedových zpráv pro pozdější zpracování aplikací pro zpracování jedů. Fronta otrávených zpráv je dílčí fronta fronty aplikace. Aplikace pro zpracování jedových zpráv může být služba WCF, která čte zprávy z jedové fronty. Jedovatá fronta je podřadí fronty aplikace a lze ji vyřešit jako net.msmq://<název_počítače>/applicationQueue; jed, kde název počítače je název počítače, na kterém se nachází fronta, a applicationQueue je název fronty specifické pro aplikaci.

Následuje maximální počet pokusů o doručení pro zprávu:

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

  • (ReceiveRetryCount + 1) v systémech Windows Server 2003 a Windows XP.

Poznámka:

Pro zprávu, která se úspěšně doručuje, se neprovedou žádné opakované pokusy.

Chcete-li sledovat počet pokusů o přečtení zprávy, systém Windows Vista udržuje odolnou vlastnost zprávy, která spočítá počet přerušení a vlastnost počtu přesunutí, která spočítá, kolikrát se zpráva pohybuje mezi frontou aplikace a dílčími frontami. Kanál WCF je používá k výpočtu počtu opakování příjmu a počtu cyklů opakování. V systémech Windows Server 2003 a Windows XP se počet přerušení udržuje v paměti kanálem WCF a v případě selhání aplikace se resetuje. Kanál WCF může také uchovávat počty přerušení až pro 256 zpráv v paměti kdykoli. Pokud se přečte 257. zpráva, obnoví se nejstarší počet přerušení zprávy.

Počet přerušení a vlastnosti počtu přesunů jsou k dispozici pro operaci služby prostřednictvím kontextu operace. Následující příklad kódu ukazuje, jak k nim získat přístup.

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 poskytuje dvě standardní vazby ve frontě:

  • NetMsmqBinding. Vazba rozhraní .NET Framework vhodná pro provádění komunikace založené na frontě s jinými koncovými body WCF.

  • MsmqIntegrationBinding. Vazba vhodná pro komunikaci se stávajícími aplikacemi služby Řízení front zpráv.

Poznámka:

Vlastnosti v těchto vazbách můžete změnit na základě požadavků vaší služby WCF. Celý mechanismus zpracování jedovatých zpráv je místní pro přijímající aplikaci. Proces není pro odesílající aplikaci neviditelný, pokud přijímající aplikace nakonec zastaví a neodešle negativní potvrzení zpět odesílateli. V takovém případě se zpráva přesune do fronty nedoručených zpráv odesílatele.

Osvědčený postup: Zpracování msmqPoisonMessageException

Když služba zjistí, že je zpráva jedovatá, vyvolá ve frontě přenos MsmqPoisonMessageException zprávu obsahující LookupId jed.

Přijímající aplikace může implementovat IErrorHandler rozhraní pro zpracování chyb, které aplikace vyžaduje. Další informace najdete v tématu Rozšíření kontroly nad zpracováním chyb a generováním sestav.

Aplikace může vyžadovat určitý druh automatizovaného zpracování otrávených zpráv, které přesunou jedové zprávy do fronty otrávených zpráv, aby služba mohla přistupovat ke zbytku zpráv ve frontě. Jediný scénář použití mechanismu obslužné rutiny chyby k naslouchání výjimky je, když ReceiveErrorHandling je nastavení nastaveno na Faulthodnotu . Ukázka otrávené zprávy pro službu Řízení front zpráv 3.0 ukazuje toto chování. Následující kroky popisují, jak zpracovat otrávené zprávy, včetně osvědčených postupů:

  1. Ujistěte se, že nastavení jedu odpovídá požadavkům vaší aplikace. Při práci s nastavením se ujistěte, že rozumíte rozdílům mezi možnostmi služby Řízení front zpráv v systémech Windows Vista, Windows Server 2003 a Windows XP.

  2. V případě potřeby implementujte IErrorHandler zpracování chyb otrávené zprávy. Vzhledem k tomu, že nastavení ReceiveErrorHandling vyžaduje Fault ruční mechanismus pro přesunutí otrávené zprávy z fronty nebo k opravě externího závislého problému, je typické použití implementovat IErrorHandler , pokud ReceiveErrorHandling je nastavena na Fault, jak je znázorněno v následujícím kódu.

    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. PoisonBehaviorAttribute Vytvořte, aby chování služby bylo možné použít. Chování nainstaluje na IErrorHandler dispečera. Podívejte se na následující příklad kódu.

    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. Ujistěte se, že je vaše služba opatřena poznámkami atributem chování jedu.

Kromě toho, pokud je nastavena ReceiveErrorHandling na Fault, ServiceHost chyby při výskytu jedovaté zprávy. Můžete připojit k chybné události a vypnout službu, provést nápravné akce a restartovat. Například LookupId v šířeném MsmqPoisonMessageException souboru lze IErrorHandler zaznamenat a když dojde k chybám hostitele služby, můžete pomocí System.Messaging rozhraní API přijmout zprávu z fronty pomocí LookupId příkazu k odebrání zprávy z fronty a uložení zprávy do některého externího úložiště nebo jiné fronty. Potom můžete restartovat ServiceHost , abyste obnovili normální zpracování. Zpracování otrávené zprávy v MSMQ 4.0 ukazuje toto chování.

Vypršení časového limitu transakce a otrávené zprávy

Mezi kanálem přenosu ve frontě a uživatelským kódem může dojít ke třídě chyb. Tyto chyby mohou být zjištěny vrstvami mezi, jako je vrstva zabezpečení zpráv nebo logika odesílání služby. Například chybějící certifikát X.509 zjištěný ve vrstvě zabezpečení SOAP a chybějící akce jsou případy, kdy se zpráva odešle do aplikace. V takovém případě model služby zprávu zahodí. Vzhledem k tomu, že zpráva je přečtená v transakci a výsledek pro tuto transakci nelze poskytnout, transakce nakonec vyprší časový limit, přeruší a zpráva se vrátí do fronty. Jinými slovy, pro určitou třídu chyb transakce se okamžitě přeruší, ale počká, dokud transakce nevyvolá časový limit. K úpravě časového limitu transakce pro službu můžete použít ServiceBehaviorAttribute.

Chcete-li změnit časový limit transakce na úrovni počítače, upravte soubor machine.config a nastavte příslušný časový limit transakce. Je důležité si uvědomit, že v závislosti na časovém limitu nastaveném v transakci se transakce nakonec přeruší a vrátí se do fronty a její počet přerušení se zvýší. Zpráva se nakonec stane jedem a správná dispozice se vytvoří podle uživatelského nastavení.

Relace a otrávené zprávy

Relace prochází stejnými postupy opakování a zpracování otrávených zpráv jako jedna zpráva. Vlastnosti dříve uvedené pro otrávené zprávy platí pro celou relaci. To znamená, že se celá relace opakuje a přejde do konečné fronty jedovatých zpráv nebo fronty nedoručených zpráv odesílatele, pokud je zpráva odmítnuta.

Dávkové a otrávené zprávy

Pokud se zpráva stane otrávenou zprávou a je součástí dávky, vrátí se celá dávka zpět a kanál se vrátí k přečtení jedné zprávy najednou. Další informace o dávkování naleznete v tématu Dávkování zpráv v transakci

Zpracování otrávených zpráv pro zprávy ve frontě jedů

Zpracování otrávených zpráv nekončí, když je zpráva umístěna do fronty jedových zpráv. Zprávy ve frontě jedovatých zpráv musí být stále přečtené a zpracovávané. Při čtení zpráv z konečného podkapultu jedu můžete použít podmnožinu nastavení zpracování jedových zpráv. Příslušná nastavení jsou ReceiveRetryCount a ReceiveErrorHandling. Můžete nastavit ReceiveErrorHandling možnost Vypustit, Odmítnout nebo Chyba. MaxRetryCycles je ignorována a pokud je nastavena možnost Přesunout, vyvolá ReceiveErrorHandling se výjimka.

Rozdíly v systémech Windows Vista, Windows Server 2003 a Windows XP

Jak jsme uvedli dříve, ne všechna nastavení zpracování jed-zpráva platí pro Systém Windows Server 2003 a Windows XP. Následující hlavní rozdíly mezi službou Řízení front zpráv v systémech Windows Server 2003, Windows XP a Windows Vista jsou relevantní pro zpracování otrávené zprávy:

  • Řízení front zpráv v systému Windows Vista podporuje dílčí fronty, zatímco systém Windows Server 2003 a Windows XP nepodporují dílčí fronty. Dílčí fronty se používají při zpracování jedových zpráv. Fronty opakování a jedová fronta jsou podřadné do fronty aplikace vytvořené na základě nastavení zpracování jedových zpráv. Určuje MaxRetryCycles , kolik dílčích front opakování se má vytvořit. Proto při spuštění v systému Windows Server 2003 nebo Windows XP MaxRetryCycles jsou ignorovány a ReceiveErrorHandling.Move nejsou povoleny.

  • Řízení front zpráv v systému Windows Vista podporuje negativní potvrzení, zatímco systém Windows Server 2003 a Windows XP ne. Záporné potvrzení od správce přijímající fronty způsobí, že odesílající správce fronty umístí odmítnutou zprávu do fronty nedoručených zpráv. ReceiveErrorHandling.Reject Proto není povoleno se systémem Windows Server 2003 a Windows XP.

  • Služba Řízení front zpráv v systému Windows Vista podporuje vlastnost zprávy, která uchovává počet pokusů o doručení zprávy. Tato vlastnost počtu přerušení není k dispozici v systémech Windows Server 2003 a Windows XP. WCF udržuje počet přerušení v paměti, takže je možné, že tato vlastnost nemusí obsahovat přesnou hodnotu, pokud stejnou zprávu přečte více než jedna služba WCF ve farmě.

Viz také