Obsługa komunikatów zanieczyszczonych

Komunikat trucizny to komunikat , który przekroczył maksymalną liczbę prób dostarczenia do aplikacji. Taka sytuacja może wystąpić, gdy aplikacja oparta na kolejce nie może przetworzyć komunikatu z powodu błędów. Aby spełnić wymagania dotyczące niezawodności, aplikacja w kolejce odbiera komunikaty w ramach transakcji. Przerywanie transakcji, w której odebrano komunikat w kolejce, powoduje pozostawienie komunikatu w kolejce, tak aby komunikat został ponowiony w ramach nowej transakcji. Jeśli problem, który spowodował przerwanie transakcji, nie zostanie rozwiązany, aplikacja odbierającą może utknąć w pętli odbieranej i przerywając ten sam komunikat do momentu przekroczenia maksymalnej liczby prób dostarczenia i wyników komunikatu trucizny.

Wiadomość może stać się wiadomością trucizny z wielu powodów. Najczęstsze przyczyny są specyficzne dla aplikacji. Jeśli na przykład aplikacja odczytuje komunikat z kolejki i wykonuje pewne przetwarzanie bazy danych, aplikacja może nie uzyskać blokady bazy danych, powodując przerwanie transakcji. Ponieważ transakcja bazy danych została przerwana, komunikat pozostaje w kolejce, co powoduje ponowne odczytanie komunikatu przez aplikację po raz drugi i podjęcie kolejnej próby uzyskania blokady w bazie danych. Komunikaty mogą również stać się trucizną, jeśli zawierają nieprawidłowe informacje. Na przykład zamówienie zakupu może zawierać nieprawidłowy numer klienta. W takich przypadkach aplikacja może dobrowolnie przerwać transakcję i zmusić komunikat do zostaniu komunikatem trucizny.

W rzadkich przypadkach komunikaty mogą nie być wysyłane do aplikacji. Warstwa programu Windows Communication Foundation (WCF) może napotkać problem z komunikatem, na przykład jeśli komunikat zawiera nieprawidłową ramkę, dołączone nieprawidłowe poświadczenia komunikatu lub nieprawidłowy nagłówek akcji. W takich przypadkach aplikacja nigdy nie odbiera komunikatu; jednak komunikat nadal może stać się komunikatem trucizny i być przetwarzany ręcznie.

Obsługa komunikatów otrutych

W programie WCF obsługa komunikatów trucizny zapewnia mechanizm odbierania aplikacji do obsługi komunikatów, których nie można wysłać do aplikacji lub komunikatów wysyłanych do aplikacji, ale które nie mogą być przetwarzane z powodu przyczyn specyficznych dla aplikacji. Skonfiguruj obsługę komunikatów trucizny przy użyciu następujących właściwości w każdym z dostępnych powiązań w kolejce:

  • ReceiveRetryCount. Wartość całkowita wskazująca maksymalną liczbę ponownych prób dostarczenia komunikatu z kolejki aplikacji do aplikacji. Domyślna wartość wynosi 5. Jest to wystarczające w przypadkach, gdy natychmiastowa ponowna próba rozwiąże problem, na przykład w przypadku tymczasowego zakleszczenia w bazie danych.

  • MaxRetryCycles. Wartość całkowita wskazująca maksymalną liczbę cykli ponawiania prób. Cykl ponawiania prób składa się z przesyłania komunikatu z kolejki aplikacji do pod kolejki ponawiania i po skonfigurowaniu opóźnienia z kolejki ponawiania prób z powrotem do kolejki aplikacji w celu ponownego dostarczenia. Domyślna wartość wynosi 2. W systemie Windows Vista komunikat jest wypróbowany maksymalnie (ReceiveRetryCount +1) * (MaxRetryCycles + 1) razy. MaxRetryCycles jest ignorowany w systemach Windows Server 2003 i Windows XP.

  • RetryCycleDelay. Opóźnienie czasowe między cyklami ponawiania prób. Wartość domyślna to 30 minut. MaxRetryCycles i RetryCycleDelay razem zapewniają mechanizm rozwiązywania problemu polegającego na tym, że ponawianie próby po okresowym opóźnieniu rozwiązuje problem. Na przykład obsługuje zablokowany wiersz ustawiony w oczekującym zatwierdzeniu transakcji programu SQL Server.

  • ReceiveErrorHandling. Wyliczenie wskazujące akcję do wykonania dla komunikatu, który zakończył się niepowodzeniem po próbie maksymalnej liczby ponownych prób. Wartościami mogą być Błędy, Upuść, Odrzuć i Przenieś. Domyślną opcją jest Błąd.

  • Usterki. Ta opcja wysyła błąd do odbiornika, który spowodował ServiceHost błąd. Komunikat musi zostać usunięty z kolejki aplikacji przez jakiś mechanizm zewnętrzny, zanim aplikacja będzie mogła nadal przetwarzać komunikaty z kolejki.

  • Upuść. Ta opcja odrzuca komunikat trucizny, a komunikat nigdy nie jest dostarczany do aplikacji. Jeśli właściwość komunikatu TimeToLive wygasła w tym momencie, komunikat może pojawić się w kolejce utraconych wiadomości nadawcy. Jeśli tak nie jest, komunikat nie jest wyświetlany nigdzie. Ta opcja wskazuje, że użytkownik nie określił, co zrobić, jeśli komunikat zostanie utracony.

  • Odrzucić. Ta opcja jest dostępna tylko w systemie Windows Vista. Powoduje to, że usługa kolejkowania komunikatów (MSMQ) wysyła negatywną potwierdzenie z powrotem do menedżera kolejki wysyłającej, że aplikacja nie może odebrać komunikatu. Komunikat jest umieszczany w kolejce utraconych komunikatów menedżera kolejki wysyłania.

  • Przenieść. Ta opcja jest dostępna tylko w systemie Windows Vista. Spowoduje to przeniesienie komunikatu trucizny do kolejki komunikatów trucizny w celu późniejszego przetworzenia przez aplikację do obsługi komunikatów trucizny. Kolejka komunikatów otruciu jest pod kolejką kolejki aplikacji. Aplikacja do obsługi komunikatów trucizny może być usługą WCF, która odczytuje komunikaty z kolejki trucizny. Kolejka trucizny jest kolejką podrzędną kolejki aplikacji i może zostać skierowana jako net.msmq://<nazwa-maszyny>/applicationQueue; trucizna, gdzie nazwa maszyny jest nazwą komputera, na którym znajduje się kolejka, a applicationQueue jest nazwą kolejki specyficznej dla aplikacji.

Poniżej przedstawiono maksymalną liczbę prób dostarczenia dla komunikatu:

  • ((ReceiveRetryCount+1) * (MaxRetryCycles + 1)) w systemie Windows Vista.

  • (ReceiveRetryCount + 1) w systemach Windows Server 2003 i Windows XP.

Uwaga

Żadne ponowne próby nie są tworzone dla komunikatu, który został pomyślnie dostarczony.

Aby śledzić liczbę prób odczytu komunikatu, system Windows Vista utrzymuje trwałą właściwość komunikatu, która zlicza liczbę przerwań i właściwość count przenoszenia, która zlicza liczbę przesłonięć komunikatów między kolejkami aplikacji i pod kolejkami. Kanał WCF używa tych elementów do obliczenia liczby ponownych prób odbierania i liczby cykli ponawiania. W systemach Windows Server 2003 i Windows XP liczba przerwań jest utrzymywana w pamięci przez kanał WCF i jest resetowany, jeśli aplikacja ulegnie awarii. Ponadto kanał WCF może przechowywać liczbę przerwań dla maksymalnie 256 komunikatów w pamięci w dowolnym momencie. Jeśli zostanie odczytany komunikat 257, zostanie zresetowana liczba przerwania najstarszej wiadomości.

Właściwości liczby przerwań i liczby przenoszenia są dostępne dla operacji usługi za pośrednictwem kontekstu operacji. Poniższy przykład kodu pokazuje, jak uzyskać do nich dostęp.

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 ...

Program WCF udostępnia dwa standardowe powiązania w kolejce:

  • NetMsmqBinding. Powiązanie programu .NET Framework odpowiednie do przeprowadzania komunikacji opartej na kolejce z innymi punktami końcowymi programu WCF.

  • MsmqIntegrationBinding. Powiązanie odpowiednie do komunikowania się z istniejącymi aplikacjami kolejkowania komunikatów.

Uwaga

Właściwości tych powiązań można zmienić na podstawie wymagań usługi WCF. Cały mechanizm obsługi komunikatów trucizny jest lokalny dla aplikacji odbierającego. Proces jest niewidoczny dla aplikacji wysyłającej, chyba że aplikacja odbierającego ostatecznie zatrzymuje się i wysyła negatywne potwierdzenie z powrotem do nadawcy. W takim przypadku komunikat jest przenoszony do kolejki utraconych wiadomości nadawcy.

Najlepsze rozwiązanie: obsługa wyjątku MsmqPoisonMessageException

Gdy usługa ustali, że komunikat jest trucizną, transport w kolejce zgłasza MsmqPoisonMessageException komunikat zawierający LookupId komunikat trucizny.

Aplikacja odbierającą może zaimplementować IErrorHandler interfejs, aby obsługiwać wszelkie błędy wymagane przez aplikację. Aby uzyskać więcej informacji, zobacz Rozszerzanie kontroli nad obsługą błędów i raportowaniem.

Aplikacja może wymagać jakiejś zautomatyzowanej obsługi zatrutych komunikatów, które przenoszą zatrute komunikaty do kolejki komunikatów trucizny, aby usługa mogła uzyskać dostęp do pozostałych komunikatów w kolejce. Jedynym scenariuszem użycia mechanizmu obsługi błędów do nasłuchiwania wyjątków dotyczących komunikatów otruciu jest ReceiveErrorHandling ustawienie ustawione na Faultwartość . Przykład trucizny komunikatu dla kolejkowania komunikatów 3.0 demonstruje to zachowanie. Poniżej przedstawiono kroki, które należy wykonać w celu obsługi komunikatów otrutych, w tym najlepszych rozwiązań:

  1. Upewnij się, że ustawienia trucizny odzwierciedlają wymagania aplikacji. Podczas pracy z ustawieniami upewnij się, że rozumiesz różnice między możliwościami kolejkowania komunikatów w systemie Windows Vista, Windows Server 2003 i Windows XP.

  2. W razie potrzeby zaimplementuj element IErrorHandler , aby obsługiwać błędy komunikatów o truciznie. Ponieważ ustawienie ReceiveErrorHandlingFault wymaga ręcznego mechanizmu przenoszenia komunikatu trucizny z kolejki lub do rozwiązania zewnętrznego problemu zależnego, typowe użycie polega na zaimplementowaniu IErrorHandler , gdy ReceiveErrorHandling jest ustawiona wartość Fault, jak pokazano w poniższym kodzie.

    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. Utwórz element, którego PoisonBehaviorAttribute może używać zachowanie usługi. Zachowanie instaluje IErrorHandler element na dyspozytorze. Zapoznaj się z poniższym przykładem kodu.

    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. Upewnij się, że usługa jest oznaczona adnotacją z atrybutem zachowania trucizny.

Ponadto, jeśli ReceiveErrorHandling parametr jest ustawiony na Fault, ServiceHost błędy podczas napotkania komunikatu trucizny. Możesz podłączyć się do uszkodzonego zdarzenia i zamknąć usługę, podjąć akcje naprawcze i ponownie uruchomić. Na przykład LookupId element w MsmqPoisonMessageException propagacji IErrorHandler można zauważyć, a kiedy błędy hosta usługi, można użyć System.Messaging interfejsu API do odbierania komunikatu z kolejki przy użyciu polecenia , LookupId aby usunąć komunikat z kolejki i zapisać komunikat w magazynie zewnętrznym lub innej kolejce. Następnie można ponownie uruchomić ServiceHost , aby wznowić normalne przetwarzanie. Obsługa komunikatów trucizny w programie MSMQ 4.0 demonstruje to zachowanie.

Przekroczenie limitu czasu transakcji i zatrucie komunikatów

Klasa błędów może wystąpić między kanałem transportu w kolejce a kodem użytkownika. Te błędy można wykryć za pomocą warstw między nimi, takich jak warstwa zabezpieczeń komunikatów lub logika wysyłania usługi. Na przykład brak certyfikatu X.509 wykrytego w warstwie zabezpieczeń protokołu SOAP i brakująca akcja to przypadki, w których komunikat zostanie wysłany do aplikacji. W takim przypadku model usługi pominie komunikat. Ponieważ komunikat jest odczytywany w transakcji i nie można podać wyniku dla tej transakcji, transakcja ostatecznie upłynął limit czasu, przerywa i komunikat jest umieszczany z powrotem w kolejce. Innymi słowy, w przypadku określonej klasy błędów transakcja nie przerywa się natychmiast, ale czeka na limit czasu transakcji. Limit czasu transakcji dla usługi można zmodyfikować przy użyciu polecenia ServiceBehaviorAttribute.

Aby zmienić limit czasu transakcji dla całego komputera, zmodyfikuj plik machine.config i ustaw odpowiedni limit czasu transakcji. Należy pamiętać, że w zależności od limitu czasu ustawionego w transakcji transakcja transakcja ostatecznie przerywa i wraca do kolejki, a jej liczba przerwań jest zwiększana. W końcu komunikat staje się trucizną, a właściwe usunięcie jest wykonywane zgodnie z ustawieniami użytkownika.

Sesje i komunikaty zatrute

Sesja przechodzi te same procedury ponawiania i obsługi komunikatów trucizny jako pojedynczy komunikat. Właściwości wymienione wcześniej dla komunikatów trucizny dotyczą całej sesji. Oznacza to, że cała sesja jest ponawiana i przechodzi do końcowej kolejki komunikatów trucizny lub kolejki utraconych wiadomości nadawcy, jeśli komunikat zostanie odrzucony.

Dzielenie na partie i zatrucie komunikatów

Jeśli komunikat stanie się komunikatem otrutym i jest częścią partii, cała partia zostanie wycofana, a kanał powróci do odczytu jednego komunikatu naraz. Aby uzyskać więcej informacji na temat dzielenia na partie, zobacz Batching Messages in a Transaction (Przetwarzanie wsadowe komunikatów w transakcji)

Obsługa komunikatów trucizny dla komunikatów w kolejce trucizny

Obsługa komunikatów o truciznie nie kończy się, gdy komunikat zostanie umieszczony w kolejce komunikatów otruciu. Komunikaty w kolejce otrutych komunikatach muszą być nadal odczytywane i obsługiwane. Można użyć podzbioru ustawień obsługi komunikatów trucizny podczas odczytywania komunikatów z końcowej podzapytania trucizny. Odpowiednie ustawienia to ReceiveRetryCount i ReceiveErrorHandling. Możesz ustawić wartość ReceiveErrorHandling Drop, Reject lub Fault. MaxRetryCycles wartość jest ignorowana, a w przypadku ReceiveErrorHandling ustawienia opcji Przenieś jest zgłaszany wyjątek.

Różnice między systemami Windows Vista, Windows Server 2003 i Windows XP

Jak wspomniano wcześniej, nie wszystkie ustawienia obsługi komunikatów trucizny dotyczą systemów Windows Server 2003 i Windows XP. Następujące kluczowe różnice między kolejkowaniem komunikatów w systemie Windows Server 2003, Windows XP i Windows Vista są istotne dla obsługi komunikatów trucizny:

  • Kolejkowanie komunikatów w systemie Windows Vista obsługuje kolejki podrzędne, podczas gdy systemy Windows Server 2003 i Windows XP nie obsługują podzapytania. Podzapytania są używane w obsłudze komunikatów trucizny. Kolejki ponawiania i kolejka trucizny są kolejkami podrzędnymi do kolejki aplikacji, która jest tworzona na podstawie ustawień obsługi komunikatów trucizny. Parametr MaxRetryCycles określa liczbę ponownych prób w kolejce do utworzenia. W związku z tym w przypadku uruchamiania w systemie Windows Server 2003 lub Windows XP MaxRetryCycles są ignorowane i ReceiveErrorHandling.Move niedozwolone.

  • Kolejkowanie komunikatów w systemie Windows Vista obsługuje potwierdzenie negatywne, podczas gdy systemy Windows Server 2003 i Windows XP nie. Negatywne potwierdzenie od odbierającego menedżera kolejek powoduje, że menedżer kolejek wysyłających umieścić odrzucony komunikat w kolejce utraconych komunikatów. W związku z tym ReceiveErrorHandling.Reject nie jest dozwolone w systemach Windows Server 2003 i Windows XP.

  • Kolejkowanie komunikatów w systemie Windows Vista obsługuje właściwość komunikatu, która utrzymuje liczbę prób dostarczenia komunikatów. Ta właściwość liczba przerwań nie jest dostępna w systemach Windows Server 2003 i Windows XP. Program WCF utrzymuje liczbę przerwań w pamięci, więc możliwe, że ta właściwość może nie zawierać dokładnej wartości, gdy ten sam komunikat jest odczytywany przez więcej niż jedną usługę WCF w farmie.

Zobacz też