Udostępnij za pośrednictwem


Obsługa wiadomości typu poison

W tym temacie opisano, w jeden sposób, w jaki aplikacji korzystającej z usługa Broker może wykryć skażona wiadomość i usunąć wiadomości z kolejki, bez konieczności korzystania z automatycznego skażona wiadomość wykrywać.

usługa Broker zawiera automatyczne skażona wiadomość wykrywania.Wykrywanie automatyczne skażona wiadomość ustawienie stanu kolejki na OFF, jeśli transakcja, która odbiera wiadomości z kolejki ponownie toczy się pięć razy.Funkcja ta zapewnia zabezpieczenie przed katastrofami błędów, które nie aplikacji wykrywać programowo.Jednak aplikacja nie powinien korzystające z tej funkcji dla normalnego przetwarzania.Ponieważ Wykrywanie automatyczne skażona wiadomość zatrzyma się kolejka, ta funkcja skutecznie zatrzymuje przetwarzanie wszystkich aplikacji, dopóki nie zostanie usunięty skażona wiadomość.Zamiast tego aplikacji powinien podejmować próbę do wykrywać i usuwania poison wiadomości jako część logiki aplikacji.

Strategii, opisane w tej sekcji przyjęto założenie, że wiadomości powinny zostać usunięte, jeśli synchronizacja nie powiedzie się określoną liczbę razy.Dla wielu aplikacji to założenie jest prawidłowa.Jednak przed użyciem tej strategii w aplikacji, należy wziąć pod uwagę na następujące pytania:

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

  • Można aplikacji szybkie i niezawodne sprawdzić zawartość wiadomości, aby wykryć, że może on nigdy nie powiodła?Jeśli tak, to strategię lepsze niż zliczania, ile razy program nie może przetworzyć tej wiadomości.Na przykład nie można przetworzyć raport wydatków, która nie zawiera nazwiska pracownika lub numer identyfikacyjny pracownika.W takim przypadek program może być bardziej efektywne, jeżeli natychmiast odpowiada na wiadomość, która nie może być przetworzone z powodu błędu, a nie próby przetwarzania wiadomości.Warto również inne sprawdzania poprawności.Na przykład jeśli numer identyfikacyjny 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 jakikolwiek błąd?Jeśli aplikacja obsługuje dużej liczby wiadomości, gdy każda wiadomość ma ograniczoną użytkowania, może być najbardziej efektywne, aby natychmiast usunąć wszystkie wiadomości, która powoduje, że operacja nie powiedzie się.Na przykład jeśli wiadomość zawiera sprawozdanie z postępu z usługa miejsce docelowe, inicjujący serwisu można je odrzucić sprawozdanie z postępu puste przez zaangażowanie receive bez przetwarzania wiadomości.W takim przypadek będzie nadal konwersacji.

Po zdecydowaniu, jak aplikacja obsługuje skażona wiadomość, należy wziąć pod uwagę na następujące pytania:

  • Aplikacji powinny rejestrować awarii i zawartość wiadomości?W wielu przypadkach nie jest to konieczne.Jednak w przypadku niektórych aplikacji, zachowując zawartość wiadomości może być odpowiednie.

  • Aplikacja, należy zalogować inne informacje na temat błędu?W niektórych przypadkach można śledzić inne informacje na temat konwersacji.Na przykład można użyć widoku wykazu sys.conversation_endpoints , aby zidentyfikować wystąpienie brokera zdalnego, które skażona wiadomość wygenerowana.

  • Należy na zakończenia aplikacji konwersacji z powodu błędu, czy powinien zezwalać kontrakt dla usługa aplikacji wskazać błąd bez zamykania konwersacji?Dla wielu usług odbierania skażona wiadomość oznacza że nie można ukończyć zadania opisane w umowie.W takim przypadek aplikacji kończy się konwersacji z powodu błędu.W innych przypadkach konwersacji będzie mógł kontynuować, mimo że jeden komunikat nie powiedzie się.Na przykład usługa, które ma pobierać dane zapasów z podłogi magazynu mogą czasami otrzymywać wiadomości przy użyciu kodu nieznany części.Zamiast Kończenie konwersacji, usługa może zapisać wiadomość w osobnej tabela dla operator do przeprowadzania inspekcji w późniejszym czasie.

Przykład: Wykrywanie, wiadomości poison

To Transact-SQL w przykładzie pokazano prostą, bezstanowej usługa, która zawiera logikę służącą do obsługi wiadomości poison. Zanim procedura przechowywana odbiera wiadomość, procedura powoduje zapisanie transakcji.Podczas tej procedury nie można przetworzyć wiadomości, należy wskazać rolkach procedury transakcji z powrotem do zapisywania.Częściowego przywrócenia zwraca wiadomości do kolejki, pozostawiając posiada blokadę w grupie konwersacji dla wiadomości.Ponieważ program nadal przechowywać blokada grupa konwersacji, program może zaktualizować tabela, która przechowuje listę niedostarczone wiadomości bez ryzyka, że inny obiekt odczytujący kolejki może przetwarzać wiadomości.

W poniższym przykładzie określa metodę aktywacja przechowywanych dla 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 AdventureWorks.dbo.AddExpenseReport
              @report = @expenseReport ;
            IF @@ERROR <> 0
             BEGIN
               ROLLBACK TRANSACTION UndoReceive ;
               EXEC TrackMessage @conversationHandle ;
             END ;
            ELSE
             BEGIN
               EXEC AdventureWorks.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 przechowywana TrackMessage śledzi liczba wiadomości nie powiodło się. Jeśli wiadomości nie powiodła się przed, procedura Wstawia nowy licznik wiadomości do tabela ExpenseServiceFailedMessages. W przeciwnym wypadku procedura sprawdza licznik liczba wiadomości nie powiodło się.Procedura zwiększa licznika, gdy licznik jest mniejsza od liczby wstępnie zdefiniowanych.Kiedy licznika jest większa niż liczba wstępnie zdefiniowanych, procedura kończy konwersacji z powodu błędu i usuwa licznik dla komunikacji 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 po prostu zawiera 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 do 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

Strategię, w tym miejscu wyświetlana jest celowo proste.Pomysły w tym temacie należy używać jako podstawy do tworzenia aplikacji, która odpowiada Twoim potrzebom.Na przykład jeśli aplikacja przechowuje stanu, może być bardziej efektywne, aby dołączyć informacje o śledzeniu wiadomości nie powiodło się w tabelach stan aplikacji.

Powyższych procedur przechowywanych nie obsługują błędów, które mogłoby spowodować transakcji nie powiedzie się.Jeśli ta usługa odbiera wiadomość, która powoduje, że cała transakcja kończy się niepowodzeniem, transakcja będzie cofnąć.W takiej sytuacji pięć razy będzie wykrywanie automatyczne skażona wiadomość zestaw stan kolejki na OFF.W takim przypadek skażona wiadomość muszą być usunięte przez inną aplikację lub przez administratora.

Jeśli uważasz, że przetwarzania, należy wykonać na wiadomości może spowodować awarię transakcji, można użyć instrukcji TRY i CATCH, do obsługi błędu.Aby uzyskać więcej informacji na temat obsługi błędów Zobacz Handling Database Engine Errors.