Obsługa wiadomości Poison

W tym temacie opisano sposób, że aplikacja używająca Service Broker , można wykrywać Trująca wiadomość i usunąć wiadomości z kolejki, bez konieczności korzystania z Trująca wiadomość automatycznego wykrywania.

Service Broker umożliwia automatyczne skażona wiadomość wykrywania.skażona wiadomość automatycznego wykrywania Ustawia stan kolejki OFF, jeśli transakcja, która odbiera wiadomości z kolejki wycofuje pięć razy.Ta funkcja zapewnia zabezpieczenie przed katastrofalnych błędów, które aplikacji nie wykrywać programowo.Jednak aplikacja nie powinny polegać na tej funkcji dla normalnego przetwarzania.Ponieważ automatyczne skażona wiadomość wykrywania zatrzymuje kolejki, funkcja ta skutecznie przerywa przetwarzanie wszystkich aplikacji do skażona wiadomość jest usuwany.Zamiast tego należy próbować aplikacji wykrywać i Usuń wiadomości jako część logiki aplikacji.

Strategia opisane w tej sekcji zakłada się, że wiadomości powinny zostać usunięte, jeśli nie powiedzie się wiele razy.Dla wielu aplikacji to założenie jest prawidłowy.Jednak przed użyciem tej strategii w aplikacji, należy rozważyć następujące kwestie:

  • Jest to licznik awarii niezawodnych aplikacji?W zależności od aplikacji, mogą być zwykłe wiadomości Niepowodzenie z czas do czas.Na przykład w aplikacji zamówienia, usługa, która przetwarza zamówienia może zająć mniej przetwarzania czas niż usługa, która dodaje nowy rekord klienta.W takim przypadek może być normalny, że zamówienia dla nowego odbiorcy nie mogą być przetwarzane natychmiast.Aplikacja wymaga uwzględnić opóźnienia przy podejmowaniu decyzji, czy wiadomość jest skażona wiadomość lub nie.Usługa może być konieczne zezwolenie kilka błędów przed usunięciem wiadomości.

  • Aplikacja szybko i niezawodnie sprawdzić zawartość wiadomości do wykrywać , nigdy nie powiodło się?Jeśli tak, to strategii lepsze niż zliczania, ile razy program nie może przetworzyć komunikatu.Na przykład raport wydatków, która nie zawiera nazwisko pracownika lub numer identyfikacyjny pracownika nie można przetworzyć.W takim przypadek program może być bardziej efektywne niezwłocznie odpowie na wiadomość, która nie może być przetworzone z powodu błędu, zamiast próby przetwarzania wiadomości.Należy wziąć pod uwagę również inne sprawdzania poprawności.Na przykład jeśli identyfikator jest obecny, ale wychodzi poza zakres numerów przypisanych (na przykład liczba ujemna), aplikacja może zakończyć konwersację natychmiast.

  • Należy usunąć wiadomość po jakimkolwiek uszkodzeniu?Aplikacji obsługuje dużą liczbę wiadomości, gdzie każda wiadomość ma ograniczoną użytkowania, może być najbardziej efektywne, natychmiast usunąć wszystkie wiadomości, który powoduje, że operacja nie powiedzie się.Na przykład jeśli wiadomość zawiera sprawozdanie okresowe z usługa miejsce docelowe, inicjujący usługa może wybrać odrzucić sprawozdanie z postępu pusty zobowiązując odbioru bez przetwarzania wiadomości.W takim przypadek nadal konwersacji.

Należy rozważyć następujące pytania Po zdecydowaniu, jak aplikacja obsługuje skażona wiadomość:

  • Aplikacji należy rejestrować awarii i zawartość wiadomości?W wielu przypadkach nie jest to konieczne.Jednakże dla niektórych aplikacji zachowywanie zawartości wiadomości może być właściwe.

  • Aplikacji, należy rejestrować innych informacji o błędzie?W niektórych przypadkach można śledzić inne informacje na temat konwersacji.Na przykład można użyć widoku wykazu sys.conversation_endpoints do identyfikowania broker zdalnego wystąpienie wygenerowanego skażona wiadomość.

  • Należy na koniec aplikacji konwersacji z błędem lub kontrakt usługa pozwolić aplikacji wskazać błąd bez zamykania konwersację?Dla wielu usług odbierania skażona wiadomość oznacza, że nie można ukończyć zadania opisane w umowie.przypadek aplikacji kończy konwersacji z błędem.W innych przypadkach konwersacji można kontynuować mimo jednej wiadomości nie powiedzie się.Na przykład usługa, który odbiera dane zapasów z podłogą magazynu czasami może pojawić się komunikat z liczbą części nieznany.Zamiast Kończenie konwersacji, usługa może zapisać wiadomość w osobnej tabela dla operator do inspekcji w późniejszym czas.

Przykład: Wykrywanie wiadomości Poison

To Transact-SQL przykładzie pokazano prostą, bezpaństwowców usługa zawierającej logiki obsługi poison wiadomości.Przed procedura składowana odbiera wiadomość, procedura zapisuje transakcji.Podczas procedury nie można przetworzyć wiadomości, wskaż zwojach procedury transakcji z powrotem do zapisywania.Częściowe wycofywania zwraca wiadomość do kolejki przytrzymując wciśnięty klawisz blokada na grupa konwersacji wiadomości.Ponieważ program nadal przytrzymując blokada grupa konwersacji, program można zaktualizować tabela, która przechowuje listę niedostarczone wiadomości bez ryzyka, że inny obiekt odczytujący kolejki może przetwarzać wiadomości.

Poniższy przykład definiuje procedura składowana aktywacja aplikacji:

CREATE PROCEDURE ProcessExpenseReport
AS
BEGIN
  WHILE (1 = 1)
    BEGIN
      BEGIN TRANSACTION ;
      DECLARE @conversationHandle UNIQUEIDENTIFIER ;
      DECLARE @messageBody VARBINARY(MAX) ;
      DECLARE @messageTypeName NVARCHAR(256) ;

      SAVE TRANSACTION UndoReceive ;

        WAITFOR ( 
                  RECEIVE TOP(1)
                    @messageTypeName = message_type_name,
                    @messageBody = message_body,
                    @conversationHandle = conversation_handle
                    FROM ExpenseQueue
                 ), TIMEOUT 500 ;

        IF @@ROWCOUNT = 0
        BEGIN
          ROLLBACK TRANSACTION ;
          BREAK ;
        END ;

        -- Typical message processing loop: dispatch to a stored
        -- procedure based on the message type name.  End conversation
        -- with an error for unknown message types.

        -- Process expense report messages. If processing fails,
        -- roll back to the save point and track the failed message.

        IF (@messageTypeName =
              '//Adventure-Works.com/AccountsPayable/ExpenseReport')
          BEGIN
            DECLARE @expenseReport NVARCHAR(MAX) ;
            SET @expenseReport = CAST(@messageBody AS NVARCHAR(MAX)) ;
            EXEC AdventureWorks2008R2.dbo.AddExpenseReport
              @report = @expenseReport ;
            IF @@ERROR <> 0
             BEGIN
               ROLLBACK TRANSACTION UndoReceive ;
               EXEC TrackMessage @conversationHandle ;
             END ;
            ELSE
             BEGIN
               EXEC AdventureWorks2008R2.dbo.ClearMessageTracking
                 @conversationHandle ;
             END ;
           END ;
        ELSE

        -- For error messages and end dialog messages, end the
        -- conversation.

        IF (@messageTypeName =
              'https://schemas.microsoft.com/SQL/ServiceBroker/Error' OR
             @messageTypeName =
              'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
          BEGIN
            END CONVERSATION @conversationHandle ;
            EXEC dbo.ClearMessageTracking @conversationHandle ;
          END ;


         COMMIT TRANSACTION ;
    END ;
END ;

procedura składowana TrackMessage śledzi liczbę wiadomości nie powiodła się.Gdy wiadomości nie powiodła przed procedurą Wstawia nowy licznik wiadomości do tabela ExpenseServiceFailedMessages.W przeciwnym wypadku procedura sprawdza licznik liczbę wiadomości nie powiodło się.Procedura zwiększa licznika, gdy licznik jest mniejsza niż liczba wstępnie zdefiniowanych.Gdy licznik jest większa niż liczba wstępnie zdefiniowanych, procedura kończy konwersacji z błędem i usuwa licznik dla konwersacji z tabela.

CREATE PROCEDURE TrackMessage
@conversationHandle uniqueidentifier
AS
BEGIN
  IF @conversationHandle IS NULL
    RETURN ;

  DECLARE @count INT ;
  SET @count = NULL ;
  SET @count = (SELECT count FROM dbo.ExpenseServiceFailedMessages
                  WHERE conversation_handle = @conversationHandle) ;

  IF @count IS NULL
    BEGIN
      INSERT INTO dbo.ExpenseServiceFailedMessages
        (count, conversation_handle)
        VALUES (1, @conversationHandle) ;
    END ;
  IF @count > 3
    BEGIN
      EXEC dbo.ClearMessageTracking @conversationHandle ;
      END CONVERSATION @conversationHandle
        WITH ERROR = 500
        DESCRIPTION = 'Unable to process message.' ;
    END ;
  ELSE
    BEGIN
      UPDATE dbo.ExpenseServiceFailedMessages
        SET count=count+1
        WHERE conversation_handle = @conversationHandle ;
    END ;
END ;
GO

Definicja tabela ExpenseServiceFailedMessages zawiera po prostu conversation_handle kolumna i count kolumna, jak pokazano w następującym przykładzie:

CREATE TABLE ExpenseServiceFailedMessages (
  conversation_handle uniqueidentifier PRIMARY KEY,
  count smallint
) ;

Procedura ClearMessageTracking Usuwa licznik konwersacji z tabela ExpenseServiceFailedMessages, jak pokazano w następującym przykładzie:

CREATE PROCEDURE ClearMessageTracking
  @conversationHandle uniqueidentifier
AS
BEGIN
   DELETE FROM dbo.ExpenseServiceFailedMessages
     WHERE conversation_handle = @conversationHandle ;
END ;
GO

Strategia tu jest celowo proste.Pomysły w tym temacie należy używać jako podstawę do budowania aplikacji, która odpowiada Twoim potrzebom.Na przykład jeśli aplikacja zachowuje stan, może być bardziej efektywne zawierają informacje o śledzeniu wiadomości nie powiodło się w tabelach stan aplikacji.

Powyższe procedury przechowywane nie obsługują błędów powodujących transakcji nie powiedzie się.Jeśli ta usługa odbiera wiadomość, która powoduje, że cała transakcja nie będzie transakcji wycofać.Takim pięć razy Wykrywanie automatyczne Trująca wiadomość będzie zestaw stan kolejki do OFF.W takim przypadek skażona wiadomość muszą być usunięte przez inną aplikację lub przez administratora.

Jeśli uważasz, że przetwarzanie wykonywać na wiadomość może spowodować błąd transakcji, można użyć instrukcji TRY i połowów do obsługi błędu.Więcej informacji na temat obsługi błędów, zobacz Obsługa błędów aparatu bazy danych.