Instrukcje: obsługa błędów
W tym temacie opisano podstawowe kroki wymagane do utworzenia konfiguracji routingu korzystającej z obsługi błędów. W tym przykładzie komunikaty są kierowane do docelowego punktu końcowego. Jeśli nie można dostarczyć komunikatu z powodu błędu związanego z siecią lub komunikacją (CommunicationException), komunikat jest ponownie wysyłany do alternatywnego punktu końcowego.
Uwaga
Aby zasymulować awarię sieci, docelowy punkt końcowy używany w tym przykładzie zawiera niepoprawny adres. Komunikaty kierowane do tego punktu końcowego kończą się niepowodzeniem, ponieważ żadna usługa nie nasłuchuje na określonym adresie.
Uwaga
Chociaż przykład zawarty w tym temacie nie omawia jawnie ustawień przekroczenia limitu czasu, należy wziąć pod uwagę je podczas korzystania z obsługi błędów. W przypadku napotkania błędów zostanie napotkane dodatkowe opóźnienie, zanim klient otrzyma odpowiedź. Jest to spowodowane tym, że błąd jest odbierany w usłudze routingu, która następnie próbuje wysłać komunikat do punktu końcowego kopii zapasowej. Jeśli wartości limitu czasu skojarzone z podstawowymi i docelowymi punktami końcowymi kopii zapasowej są duże, klient może mieć duże opóźnienie, ponieważ komunikat przejdzie w tryb failover przez wiele punktów końcowych na liście kopii zapasowych przed pomyślnym wysłaniem.
Ponieważ usługa routingu może napotkać maksymalne opóźnienie równe sumie wartości limitu czasu dla wszystkich punktów końcowych skojarzonych z filtrem, zalecamy odpowiednio zwiększenie oczekiwanego limitu czasu na kliencie.
Implementowanie obsługi błędów
Utwórz podstawową konfigurację usługi routingu, określając punkt końcowy usługi uwidoczniony przez usługę. W poniższym przykładzie zdefiniowano pojedynczy punkt końcowy usługi, który jest używany do odbierania komunikatów. Definiuje również punkty końcowe klienta używane do wysyłania komunikatów; deadDestination i realDestination. Punkt końcowy deadDestination zawiera adres, który nie odwołuje się do uruchomionej usługi i służy do symulowania awarii sieci podczas wysyłania komunikatów do tego punktu końcowego.
<services> <service behaviorConfiguration="routingConfiguration" name="System.ServiceModel.Routing.RoutingService"> <host> <baseAddresses> <add baseAddress="http://localhost/routingservice/" /> </baseAddresses> </host> <!-- Create the Routing Service endpoint --> <endpoint address="router" binding="basicHttpBinding" name="RoutingServiceEndpoint" contract="System.ServiceModel.Routing.IRequestReplyRouter" /> </service> </services> <!-- Create the destination endpoints that we want to send to --> <client> <!-- Create a dummy endpoint that we know will be down --> <endpoint name="deadDestination" address="net.tcp://localhost:9090/servicemodelsamples/fakeDestination" binding="netTcpBinding" contract="*" /> <!-- Now create the real service endpoint --> <endpoint name="realDestination" address="net.tcp://localhost:8080/servicemodelsamples/service" binding="netTcpBinding" contract="*" /> </client>
Zdefiniuj filtry używane do kierowania komunikatów do docelowych punktów końcowych. W tym przykładzie filtr MatchAll jest używany do dopasowania wszystkich komunikatów odebranych przez usługę routingu.
<filters> <!-- Create a MatchAll filter which will catch all messages --> <filter name="MatchAllFilter1" filterType="MatchAll" /> </filters>
Zdefiniuj listę punktów końcowych kopii zapasowej zawierającą punkty końcowe, do których jest wysyłany komunikat w przypadku awarii sieci lub komunikacji podczas wysyłania do podstawowego punktu końcowego docelowego. W poniższym przykładzie zdefiniowano listę kopii zapasowych zawierającą jeden punkt końcowy; można jednak określić wiele punktów końcowych na liście kopii zapasowych.
Jeśli lista kopii zapasowych zawiera wiele punktów końcowych, gdy wystąpi awaria sieci lub komunikacji, usługa routingu próbuje wysłać komunikat do pierwszego punktu końcowego na liście. Jeśli podczas wysyłania do tego punktu końcowego wystąpi błąd sieci lub komunikacji, usługa routingu próbuje wysłać komunikat do następnego punktu końcowego znajdującego się na liście. Usługa kontynuuje wysyłanie komunikatu do każdego punktu końcowego na liście punktów końcowych kopii zapasowej do momentu pomyślnego wysłania komunikatu, wszystkie punkty końcowe kopii zapasowej zwracają błąd związany z siecią lub komunikacją albo komunikat jest wysyłany, a punkt końcowy zwraca błąd niesieciowy, niezwiązany z komunikacją.
<backupLists> <backupList name="backupEndpointList"> <add endpointName="realDestination" /> </backupList> </backupLists>
Zdefiniuj tabelę filtru, która kojarzy filtr z punktem końcowym deadDestination i listą punktów końcowych kopii zapasowej. Usługa routingu najpierw próbuje wysłać komunikat do docelowego punktu końcowego skojarzonego z filtrem. Ponieważ deadDestination zawiera adres, który nie odnosi się do uruchomionej usługi, powoduje to błąd sieci. Następnie usługa routingu próbuje wysłać komunikat do punktu końcowego określonego w liście backupEndpointList.
<filterTables> <!-- Set up the Routing Service's Message Filter Table --> <filterTable name="filterTable1"> <!-- Add an entity that maps the MatchAllMessageFilter to the dead destination --> <!-- If that endpoint is down, tell the Routing Service to try the endpoints --> <!-- Listed in the backupEndpointList --> <add filterName="MatchAllFilter1" endpointName="deadDestination" backupList="backupEndpointList"/> </filterTable> </filterTables>
Aby ocenić komunikaty przychodzące względem filtru zawartego w tabeli filtrów, należy skojarzyć tabelę filtrów z punktami końcowymi usługi przy użyciu zachowania routingu. W poniższym przykładzie pokazano skojarzenie elementu "filterTable1" z punktami końcowymi usługi.
<behaviors> <serviceBehaviors> <!-- Set up the Routing Behavior --> <behavior name="routingConfiguration"> <routing filterTableName="filterTable1" /> </behavior> </serviceBehaviors> </behaviors>
Przykład
Poniżej znajduje się pełna lista pliku konfiguracji:
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright (c) Microsoft Corporation. All Rights Reserved. -->
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="routingConfiguration"
name="System.ServiceModel.Routing.RoutingService">
<host>
<baseAddresses>
<add baseAddress="http://localhost/routingservice/" />
</baseAddresses>
</host>
<!-- Create the Routing Service endpoint -->
<endpoint address="router"
binding="basicHttpBinding"
name="RoutingServiceEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<!-- Set up the Routing Behavior -->
<behavior name="routingConfiguration">
<routing filterTableName="filterTable1" />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- Create the destination endpoints that we want to send to -->
<client>
<!-- Create a dummy endpoint that we know will be down -->
<endpoint name="deadDestination"
address="net.tcp://localhost:9090/servicemodelsamples/fakeDestination"
binding="netTcpBinding"
contract="*" />
<!-- Now create the real service endpoint -->
<endpoint name="realDestination"
address="net.tcp://localhost:8080/servicemodelsamples/service"
binding="netTcpBinding"
contract="*" />
</client>
<routing>
<filters>
<!-- Create a MatchAll filter which will catch all messages -->
<filter name="MatchAllFilter1" filterType="MatchAll" />
</filters>
<filterTables>
<!-- Set up the Routing Service's Message Filter Table -->
<filterTable name="filterTable1">
<!-- Add an entry that maps the MatchAllMessageFilter to the dead destination -->
<!-- If that endpoint is down, tell the Routing Service to try the endpoints -->
<!-- Listed in the backupEndpointList -->
<add filterName="MatchAllFilter1" endpointName="deadDestination" backupList="backupEndpointList"/>
</filterTable>
</filterTables>
<!-- Create the backup endpoint list -->
<backupLists>
<backupList name="backupEndpointList">
<add endpointName="realDestination" />
</backupList>
</backupLists>
</routing>
</system.serviceModel>
</configuration>