Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der Routingdienst bietet einen generischen austauschbaren SOAP-Vermittler, der Nachrichten basierend auf Nachrichteninhalten weiterleiten kann. Mit dem Routingdienst können Sie komplexe Routinglogik erstellen, mit der Sie Szenarien wie Dienstaggregation, Dienstversionsverwaltung, Prioritätsrouting und Multicastrouting implementieren können. Der Routingdienst bietet auch eine Fehlerbehandlung, mit der Sie Listen von Sicherungsendpunkten einrichten können, an die Nachrichten gesendet werden, wenn beim Senden an den primären Zielendpunkt ein Fehler auftritt.
Dieses Thema ist für diejenigen gedacht, die mit dem Routingdienst neu sind und die grundlegende Konfiguration und das Hosting des Routingdiensts abdecken.
Konfiguration
Der Routingdienst wird als WCF-Dienst implementiert, der einen oder mehrere Dienstendpunkte verfügbar macht, die Nachrichten von Clientanwendungen empfangen und die Nachrichten an einen oder mehrere Zielendpunkte weiterleiten. Der Dienst stellt ein RoutingBehavior-Objekt bereit, das auf die vom Dienst verfügbar gemachten Dienstendpunkte angewendet wird. Dieses Verhalten wird verwendet, um verschiedene Aspekte der Funktionsweise des Diensts zu konfigurieren. Um die Konfiguration zu vereinfachen, wenn Sie eine Konfigurationsdatei verwenden, werden die Parameter für RoutingBehavior angegeben. In codebasierten Szenarien würden diese Parameter als Teil eines RoutingConfiguration Objekts angegeben, das dann an ein RoutingBehavior übergeben werden kann.
Beim Starten fügt dieses Verhalten den Clientendpunkten das SoapProcessingBehavior hinzu. Dieses Verhalten wird für die SOAP-Verarbeitung von Nachrichten verwendet. Dadurch kann der Routingdienst Nachrichten an Endpunkte übertragen, für die eine andere MessageVersion erforderlich ist als der Endpunkt, über den die Nachricht empfangen wurde. Das RoutingBehavior registriert auch eine Diensterweiterung, die RoutingExtension als Zugriffspunkt dient, um die Routingdienstkonfiguration zur Laufzeit zu ändern.
Die RoutingConfiguration-Klasse bietet ein konsistentes Mittel zum Konfigurieren und Aktualisieren der Konfiguration des Routingdiensts. Sie enthält Parameter, die als Einstellungen für den Routingdienst fungieren und zum Konfigurieren des RoutingBehavior beim Starten des Diensts verwendet werden oder an routingExtension übergeben werden, um die Routingkonfiguration zur Laufzeit zu ändern.
Die Routinglogik zur Durchführung inhaltsbasierter Weiterleitung von Nachrichten wird definiert, indem mehrere MessageFilter Objekte in Filtertabellen (MessageFilterTable<TFilterData> Objekte) gruppiert werden. Eingehende Nachrichten werden anhand der Nachrichtenfilter ausgewertet, die in der Filtertabelle enthalten sind, und für jeden MessageFilter , der der Nachricht entspricht, die an einen Zielendpunkt weitergeleitet wird. Die Filtertabelle, die zum Weiterleiten von Nachrichten verwendet werden soll, wird entweder mithilfe des RoutingBehavior in der Konfiguration oder mithilfe von Code mithilfe des RoutingConfiguration-Objekts angegeben.
Definieren von Endpunkten
Es mag zwar vorkommen, dass Sie ihre Konfiguration starten sollten, indem Sie die verwendete Routinglogik definieren. Der erste Schritt sollte jedoch darin bestehen, die Form der Endpunkte zu bestimmen, an die Sie Nachrichten weiterleiten werden. Der Routingdienst verwendet Verträge, die die Form der Kanäle definieren, die zum Empfangen und Senden von Nachrichten verwendet werden, und daher muss das Shape des Eingabekanals mit dem des Ausgabekanals übereinstimmen. Wenn Sie beispielsweise an Endpunkte weiterleiten, die den Anforderungs-Antwort-Kanal nutzen, müssen Sie einen kompatiblen Vertrag für die eingehenden Endpunkte verwenden, wie etwa IRequestReplyRouter.
Dies bedeutet, dass wenn Ihre Zielendpunkte Verträge mit mehreren Kommunikationsmustern (z. B. das Mischen von unidirektionalen und bidirektionalen Vorgängen) verwenden, Sie keinen einzelnen Dienstendpunkt erstellen können, der Nachrichten an alle empfangen und weiterleiten kann. Sie müssen bestimmen, welche Endpunkte kompatible Shapes haben und einen oder mehrere Dienstendpunkte definieren, die zum Empfangen von Nachrichten verwendet werden, die an die Zielendpunkte weitergeleitet werden sollen.
Hinweis
Beim Arbeiten mit Verträgen, die mehrere Kommunikationsmuster angeben (z. B. eine Mischung aus unidirektionalen und bidirektionalen Operationen), besteht eine Lösung darin, einen Duplex-Vertrag beim Routingdienst wie IDuplexSessionRouter zu verwenden. Dies bedeutet jedoch, dass die Bindung in der Lage sein muss, die Duplexkommunikation zu ermöglichen, was für alle Szenarien möglicherweise nicht möglich ist. In Szenarien, in denen dies nicht möglich ist, kann es erforderlich sein, die Kommunikation in mehrere Endpunkte zu integrieren oder die Anwendung zu ändern.
Weitere Informationen zu Routingverträgen finden Sie unter Routingverträge.
Nachdem der Dienstendpunkt definiert wurde, können Sie routingBehavior verwenden, um dem Endpunkt eine bestimmte RoutingConfiguration zuzuordnen. Beim Konfigurieren des Routingdiensts mithilfe einer Konfigurationsdatei wird routingBehavior verwendet, um die Filtertabelle anzugeben, die die Routinglogik enthält, die zum Verarbeiten von Nachrichten verwendet wird, die auf diesem Endpunkt empfangen werden. Wenn Sie den Routingdienst programmgesteuert konfigurieren, können Sie die Filtertabelle mithilfe der RoutingConfiguration angeben.
Im folgenden Beispiel werden die Dienst- und Clientendpunkte definiert, die vom Routingdienst sowohl programmgesteuert als auch mithilfe einer Konfigurationsdatei verwendet werden.
<services>
<!--ROUTING SERVICE -->
<service behaviorConfiguration="routingData"
name="System.ServiceModel.Routing.RoutingService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/routingservice/router"/>
</baseAddresses>
</host>
<!-- Define the service endpoints that are receive messages -->
<endpoint address=""
binding="wsHttpBinding"
name="reqReplyEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="routingData">
<serviceMetadata httpGetEnabled="True"/>
<!-- Add the RoutingBehavior and specify the Routing Table to use -->
<routing filterTableName="routingTable1" />
</behavior>
</serviceBehaviors>
</behaviors>
<client>
<!-- Define the client endpoint(s) to route messages to -->
<endpoint name="CalculatorService"
address="http://localhost:8000/servicemodelsamples/service"
binding="wsHttpBinding" contract="*" />
</client>
//set up some communication defaults
string clientAddress = "http://localhost:8000/servicemodelsamples/service";
string routerAddress = "http://localhost:8000/routingservice/router";
Binding routerBinding = new WSHttpBinding();
Binding clientBinding = new WSHttpBinding();
//add the endpoint the router uses to receive messages
serviceHost.AddServiceEndpoint(
typeof(IRequestReplyRouter),
routerBinding,
routerAddress);
//create the client endpoint the router routes messages to
ContractDescription contract = ContractDescription.GetContract(
typeof(IRequestReplyRouter));
ServiceEndpoint client = new ServiceEndpoint(
contract,
clientBinding,
new EndpointAddress(clientAddress));
//create a new routing configuration object
RoutingConfiguration rc = new RoutingConfiguration();
….
rc.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
//attach the behavior to the service host
serviceHost.Description.Behaviors.Add(
new RoutingBehavior(rc));
In diesem Beispiel wird der Routingdienst so konfiguriert, dass ein einzelner Endpunkt mit einer Adresse verfügbar http://localhost:8000/routingservice/routergemacht wird, der zum Empfangen von Nachrichten verwendet wird, die weitergeleitet werden sollen. Da die Nachrichten an Anforderungsantwortendpunkte weitergeleitet werden, verwendet der Dienstendpunkt den IRequestReplyRouter Vertrag. Diese Konfiguration definiert auch einen einzelnen Clientendpunkt dieser http://localhost:8000/servicemodelsample/service Nachrichten, an die Nachrichten weitergeleitet werden. Die Filtertabelle (nicht angezeigt) mit dem Namen "routingTable1" enthält die Routinglogik, die zum Weiterleiten von Nachrichten verwendet wird, und wird dem Dienstendpunkt mithilfe der RoutingBehavior (für eine Konfigurationsdatei) oder RoutingConfiguration (für die programmgesteuerte Konfiguration) zugeordnet.
Routinglogik
Um die Routinglogik zu definieren, die zum Weiterleiten von Nachrichten verwendet wird, müssen Sie bestimmen, auf welche Daten innerhalb der eingehenden Nachrichten eindeutig reagiert werden können. Wenn Sie beispielsweise alle Zielendpunkte, zu denen Sie weiterleiten, dieselben SOAP-Aktionen verwenden, ist der Wert der in der Nachricht enthaltenen Aktion kein guter Indikator dafür, an welchen spezifischen Endpunkt die Nachricht weitergeleitet werden soll. Wenn Sie Nachrichten eindeutig an einen bestimmten Endpunkt weiterleiten müssen, sollten Sie nach Daten filtern, die den Zielendpunkt eindeutig identifiziert, an den die Nachricht weitergeleitet wird.
Der Routingdienst stellt mehrere MessageFilter-Implementierungen bereit, die bestimmte Werte innerhalb der Nachricht prüfen, z. B. Adresse, Aktion, Endpunktname oder sogar eine XPath-Abfrage. Wenn keine dieser Implementierungen Ihren Anforderungen entspricht, können Sie eine benutzerdefinierte MessageFilter-Implementierung erstellen. Weitere Informationen zu Nachrichtenfiltern und einen Vergleich der vom Routingdienst verwendeten Implementierungen finden Sie unter "Nachrichtenfilter " und "Auswählen eines Filters".
Mehrere Nachrichtenfilter werden in Filtertabellen organisiert, die jeden MessageFilter einem Zielendpunkt zuordnen. Optional kann die Filtertabelle auch verwendet werden, um eine Liste der Sicherungsendpunkte anzugeben, an die der Routingdienst versucht, die Nachricht im Falle eines Übertragungsausfalls zu senden.
Standardmäßig werden alle Nachrichtenfilter in einer Filtertabelle gleichzeitig ausgewertet; Sie können jedoch angeben Priority , dass die Nachrichtenfilter in einer bestimmten Reihenfolge ausgewertet werden. Alle Einträge mit der höchsten Priorität werden zuerst ausgewertet, und Nachrichtenfilter mit niedrigeren Prioritäten werden nicht ausgewertet, wenn eine Übereinstimmung auf einer Ebene mit höherer Priorität gefunden wird. Weitere Informationen zu Filtertabellen finden Sie unter "Nachrichtenfilter".
In den folgenden Beispielen wird MatchAllMessageFilter verwendet, das für alle Nachrichten zu true ausgewertet wird. Dieser MessageFilter wird der Filtertabelle "routingTable1" hinzugefügt, die den MessageFilter dem Clientendpunkt namens "CalculatorService" zuordnet. Der RoutingBehavior gibt dann an, dass diese Tabelle zum Weiterleiten von Nachrichten verwendet werden soll, die vom Dienstendpunkt verarbeitet werden.
<behaviors>
<serviceBehaviors>
<behavior name="routingData">
<serviceMetadata httpGetEnabled="True"/>
<!-- Add the RoutingBehavior and specify the Routing Table to use -->
<routing filterTableName="routingTable1" />
</behavior>
</serviceBehaviors>
</behaviors>
<!--ROUTING SECTION -->
<routing>
<filters>
<filter name="MatchAllFilter1" filterType="MatchAll" />
</filters>
<filterTables>
<table name="routingTable1">
<filters>
<add filterName="MatchAllFilter1" endpointName="CalculatorService" />
</filters>
</table>
</filterTables>
</routing>
//create a new routing configuration object
RoutingConfiguration rc = new RoutingConfiguration();
//create the endpoint list that contains the endpoints to route to
//in this case we have only one
List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>();
endpointList.Add(client);
//add a MatchAll filter to the Router's filter table
//map it to the endpoint list defined earlier
//when a message matches this filter, it is sent to the endpoint contained in the list
rc.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
Hinweis
Standardmäßig wertet der Routingdienst nur die Kopfzeilen der Nachricht aus. Damit die Filter auf den Nachrichtentext zugreifen können, müssen Sie RouteOnHeadersOnly auf false setzen.
Multicast-
Während viele Routingdienstkonfigurationen exklusive Filterlogik verwenden, die Nachrichten nur an einen bestimmten Endpunkt weiterleitet, müssen Sie eine bestimmte Nachricht möglicherweise an mehrere Zielendpunkte weiterleiten. Um eine Nachricht an mehrere Ziele zu multicasten, müssen die folgenden Bedingungen erfüllt sein:
Die Kanalform darf kein Request-Reply-Muster sein (kann jedoch unidirektional oder duplex sein), da die Clientanwendung nur eine Antwort auf die Anforderung empfangen kann.
Mehrere Filter müssen beim Auswerten der Nachricht
truezurückgeben.
Wenn diese Bedingungen erfüllt sind, wird die Nachricht an alle Endpunkte aller Filter weitergeleitet, die zu true ausgewertet werden. Im folgenden Beispiel wird eine Routingkonfiguration definiert, die dazu führt, dass Nachrichten an beide Endpunkte weitergeleitet werden, wenn die Endpunktadresse in der Nachricht lautet http://localhost:8000/routingservice/router/rounding.
<!--ROUTING SECTION -->
<routing>
<filters>
<filter name="MatchAllFilter1" filterType="MatchAll" />
<filter name="RoundingFilter1" filterType="EndpointAddress"
filterData="http://localhost:8000/routingservice/router/rounding" />
</filters>
<filterTables>
<table name="routingTable1">
<filters>
<add filterName="MatchAllFilter1" endpointName="CalculatorService" />
<add filterName="RoundingFilter1" endpointName="RoundingCalcService" />
</filters>
</table>
</filterTables>
</routing>
rc.FilterTable.Add(new MatchAllMessageFilter(), calculatorEndpointList);
rc.FilterTable.Add(new EndpointAddressMessageFilter(new EndpointAddress(
"http://localhost:8000/routingservice/router/rounding")),
roundingCalcEndpointList);
SOAP-Verarbeitung
Um das Routing von Nachrichten zwischen unterschiedlichen Protokollen zu unterstützen, fügt RoutingBehavior standardmäßig das SoapProcessingBehavior zu allen Clientendpunkten hinzu, an die Nachrichten weitergeleitet werden. Dieses Verhalten erstellt automatisch eine neue MessageVersion vor dem Weiterleiten der Nachricht an den Endpunkt sowie das Erstellen einer kompatiblen MessageVersion für jedes Antwortdokument, bevor sie an die anfordernde Clientanwendung zurückgegeben wird.
Die Schritte zum Erstellen einer neuen MessageVersion für die ausgehende Nachricht lauten wie folgt:
Anforderungsverarbeitung
Rufen Sie die MessageVersion der ausgehenden Bindung bzw. des Kanals ab.
Rufen Sie den Textreader für die ursprüngliche Nachricht ab.
Erstellen Sie eine neue Nachricht mit der gleichen Aktion, Textreader und einer neuen MessageVersion.
Wenn Addressing != Addressing.None gilt, kopieren Sie die Header „To“, „From“, „FaultTo“ und „RelatesTo“ in die neue Nachricht.
Kopieren Sie alle Nachrichteneigenschaften in die neue Nachricht.
Speichern Sie die ursprüngliche Anforderungsnachricht, die beim Verarbeiten der Antwort verwendet werden soll.
Gibt die neue Anforderungsnachricht zurück.
Antwortverarbeitung
Rufen Sie die MessageVersion der ursprünglichen Anforderungsnachricht ab.
Rufen Sie den Textreader für die empfangene Antwortnachricht ab.
Erstellen Sie eine neue Antwortnachricht mit derselben Aktion, demselben Body-Reader und der MessageVersion der ursprünglichen Anforderungsnachricht.
Wenn Addressing != Addressing.None gilt, kopieren Sie die Header „To“, „From“, „FaultTo“ und „RelatesTo“ in die neue Nachricht.
Kopieren Sie die Nachrichteneigenschaften in die neue Nachricht.
Gibt die neue Antwortnachricht zurück.
Standardmäßig wird den Clientendpunkten das SoapProcessingBehavior automatisch durch das RoutingBehavior hinzugefügt, wenn der Dienst gestartet wird. Sie können jedoch steuern, ob die SOAP-Verarbeitung allen Clientendpunkten hinzugefügt wird, indem Sie die SoapProcessingEnabled-Eigenschaft verwenden. Sie können das Verhalten auch direkt zu einem bestimmten Endpunkt hinzufügen und dieses Verhalten auf Endpunktebene aktivieren oder deaktivieren, wenn eine genauere Kontrolle der SOAP-Verarbeitung erforderlich ist.
Hinweis
Wenn die SOAP-Verarbeitung für einen Endpunkt deaktiviert ist, der eine andere MessageVersion als die der ursprünglichen Anforderungsnachricht erfordert, müssen Sie einen benutzerdefinierten Mechanismus zum Ausführen von SOAP-Änderungen bereitstellen, die vor dem Senden der Nachricht an den Zielendpunkt erforderlich sind.
In den folgenden Beispielen wird die soapProcessingEnabled-Eigenschaft verwendet, um zu verhindern, dass soapProcessingBehavior automatisch allen Clientendpunkten hinzugefügt wird.
<behaviors>
<!--default routing service behavior definition-->
<serviceBehaviors>
<behavior name="routingConfiguration">
<routing filterTableName="filterTable1" soapProcessingEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
//create the default RoutingConfiguration
RoutingConfiguration rc = new RoutingConfiguration();
rc.SoapProcessingEnabled = false;
Dynamische Konfiguration
Wenn Sie zusätzliche Clientendpunkte hinzufügen oder die Filter ändern müssen, die zum Weiterleiten von Nachrichten verwendet werden, müssen Sie eine Möglichkeit haben, die Konfiguration dynamisch zur Laufzeit zu aktualisieren, um zu verhindern, dass der Dienst an den Endpunkten unterbrochen wird, die derzeit Nachrichten über den Routingdienst empfangen. Das Ändern einer Konfigurationsdatei oder des Codes der Hostanwendung reicht nicht immer aus, da für beide Methoden das Recycling der Anwendung erforderlich ist, was zu einem potenziellen Verlust von Nachrichten führen würde, die derzeit während der Übertragung ausgeführt werden, und das Potenzial für Ausfallzeiten beim Warten auf den Neustart des Diensts.
Sie können routingConfiguration nur programmgesteuert ändern. Sie können den Dienst zwar zunächst mithilfe einer Konfigurationsdatei konfigurieren, aber Sie können die Konfiguration zur Laufzeit nur ändern, indem Sie eine neue RoutingConfiguration erstellen und als Parameter an die Methode übergeben, die ApplyConfiguration von der RoutingExtension Diensterweiterung verfügbar gemacht wird. Alle nachrichten, die derzeit übertragen werden, werden weiterhin mithilfe der vorherigen Konfiguration weitergeleitet, während nachrichten, die nach dem Aufruf von ApplyConfiguration empfangen wurden, die neue Konfiguration verwenden. Das folgende Beispiel veranschaulicht das Erstellen einer Instanz des Routingdiensts und anschließendes Ändern der Konfiguration.
RoutingConfiguration routingConfig = new RoutingConfiguration();
routingConfig.RouteOnHeadersOnly = true;
routingConfig.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
RoutingBehavior routing = new RoutingBehavior(routingConfig);
routerHost.Description.Behaviors.Add(routing);
routerHost.Open();
// Construct a new RoutingConfiguration
RoutingConfiguration rc2 = new RoutingConfiguration();
ServiceEndpoint clientEndpoint = new ServiceEndpoint();
ServiceEndpoint clientEndpoint2 = new ServiceEndpoint();
// Add filters to the FilterTable in the new configuration
rc2.FilterTable.add(new MatchAllMessageFilter(),
new List<ServiceEndpoint>() { clientEndpoint });
rc2.FilterTable.add(new MatchAllMessageFilter(),
new List<ServiceEndpoint>() { clientEndpoint2 });
rc2.RouteOnHeadersOnly = false;
// Apply the new configuration to the Routing Service hosted in
routerHost.routerHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc2);
Hinweis
Beim Aktualisieren des Routingdiensts auf diese Weise ist es nur möglich, eine neue Konfiguration zu übergeben. Es ist nicht möglich, nur ausgewählte Elemente der aktuellen Konfiguration zu ändern oder neue Einträge an die aktuelle Konfiguration anzufügen; Sie müssen eine neue Konfiguration erstellen und übergeben, die das vorhandene ersetzt.
Hinweis
Alle Sitzungen, die mit der vorherigen Konfiguration geöffnet wurden, verwenden weiterhin die vorherige Konfiguration. Die neue Konfiguration wird nur von neuen Sitzungen verwendet.
Fehlerbehandlung
Wenn beim Versuch, eine Nachricht zu senden, ein CommunicationException auftritt, wird die Fehlerbehandlung vorgenommen. Diese Ausnahmen deuten in der Regel darauf hin, dass beim Versuch, mit dem definierten Clientendpunkt zu kommunizieren, wie z. B. ein EndpointNotFoundException, ServerTooBusyExceptionoder CommunicationObjectFaultedExceptionein Problem aufgetreten ist. Der Fehlerbehandlungscode erfasst und versucht, das Senden bei einem TimeoutException Auftreten erneut zu versuchen. Dies ist eine weitere häufige Ausnahme, die nicht von CommunicationException abgeleitet wird.
Wenn eine der vorangegangenen Ausnahmen auftritt, wechselt der Routingdienst zu einer Liste von Sicherungsendpunkten. Wenn alle Sicherungsendpunkte mit einem Kommunikationsfehler fehlschlagen oder wenn ein Endpunkt eine Ausnahme zurückgibt, die einen Fehler innerhalb des Zieldiensts angibt, gibt der Routingdienst einen Fehler an die Clientanwendung zurück.
Hinweis
Die Fehlerbehandlungsfunktionalität erfasst und verarbeitet Ausnahmen, die beim Senden einer Nachricht und beim Versuch, einen Kanal zu schließen, auftreten. Der Fehlermanagementcode soll keine Ausnahmen erkennen oder behandeln, die von den Anwendungsendpunkten erstellt wurden, mit denen er kommuniziert; ein von einem Dienst ausgelöstes FaultException erscheint beim Routingdienst als FaultMessage und wird an den Client zurückgesendet.
Wenn ein Fehler auftritt, während der Routingdienst versucht, eine Nachricht weiterzuleiten, erhalten Sie möglicherweise einen FaultException auf der Clientseite, anstelle eines EndpointNotFoundException, den Sie normalerweise ohne den Routingdienst erhalten würden. Ein Routingdienst kann daher Ausnahmen maskieren und keine vollständige Transparenz bieten, es sei denn, Sie untersuchen geschachtelte Ausnahmen.
Nachverfolgen von Ausnahmen
Wenn das Senden einer Nachricht an einen Endpunkt in einer Liste fehlschlägt, verfolgt der Routingdienst die resultierenden Ausnahmedaten und fügt die Ausnahmedetails als Nachrichteneigenschaft namens Exceptions an. Dadurch bleiben die Ausnahmedaten erhalten und ermöglicht einem Benutzer programmgesteuerten Zugriff über einen Nachrichteninspektor. Die Ausnahmedaten werden pro Nachricht in einem Wörterbuch gespeichert, das den Endpunktnamen den Ausnahmedetails zuordnet, die beim Versuch, eine Nachricht an sie zu senden, aufgetreten sind.
Sicherungsendpunkte
Jeder Filtereintrag in der Filtertabelle kann optional eine Liste von Sicherungsendpunkten angeben, die bei einem Übertragungsausfall beim Senden an den primären Endpunkt verwendet werden. Wenn ein solcher Fehler auftritt, versucht der Routingdienst, die Nachricht an den ersten Eintrag in der Sicherungsendpunktliste zu übertragen. Wenn bei diesem Sendeversuch auch ein Übertragungsfehler auftritt, wird der nächste Endpunkt in der Sicherungsliste versucht. Der Routingdienst sendet die Nachricht weiterhin an jeden Endpunkt in der Liste, bis die Nachricht erfolgreich empfangen wurde, geben alle Endpunkte einen Übertragungsfehler zurück, oder ein Nichtübertragungsfehler wird von einem Endpunkt zurückgegeben.
In den folgenden Beispielen wird der Routingdienst für die Verwendung einer Sicherungsliste konfiguriert.
<routing>
<filters>
<!-- Create a MatchAll filter that catches 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>
<!-- Add an endpoint list that contains the backup destinations -->
<backupList name="backupEndpointList">
<add endpointName="realDestination" />
<add endpointName="backupDestination" />
</backupList>
</backupLists>
</routing>
//create the endpoint list that contains the service endpoints we want to route to
List<ServiceEndpoint> backupList = new List<ServiceEndpoint>();
//add the endpoints in the order that the Routing Service should contact them
//first add the endpoint that we know is down
//clearly, normally you wouldn't know that this endpoint was down by default
backupList.Add(fakeDestination);
//then add the real Destination endpoint
//the Routing Service attempts to send to this endpoint only if it
//encounters a TimeOutException or CommunicationException when sending
//to the previous endpoint in the list.
backupList.Add(realDestination);
//add the backupDestination endpoint
//the Routing Service attempts to send to this endpoint only if it
//encounters a TimeOutException or CommunicationsException when sending
//to the previous endpoints in the list
backupList.Add(backupDestination);
//create the default RoutingConfiguration option
RoutingConfiguration rc = new RoutingConfiguration();
//add a MatchAll filter to the Routing Configuration's filter table
//map it to the list of endpoints defined above
//when a message matches this filter, it is sent to the endpoints in the list in order
//if an endpoint is down or does not respond (which the first endpoint won't
//since the client does not exist), the Routing Service automatically moves the message
//to the next endpoint in the list and try again.
rc.FilterTable.Add(new MatchAllMessageFilter(), backupList);
Unterstützte Fehlermuster
In der folgenden Tabelle werden die Muster beschrieben, die mit der Verwendung von Sicherungsendpunktlisten kompatibel sind, sowie Hinweise zur Fehlerbehandlung für bestimmte Muster.
| Muster | Sitzung | Transaktion | Empfangskontext | Unterstützte Sicherungsliste | Hinweise |
|---|---|---|---|---|---|
| Unidirektional | Ja | Versucht, die Nachricht an einen Sicherungsendpunkt erneut zu senden. Wenn diese Nachricht als Multicast gesendet wird, wird nur die Nachricht auf dem fehlgeschlagenen Kanal an ihr Sicherungsziel verschoben. | |||
| Unidirektional | ✔️ | Nein | Eine Ausnahme wird ausgelöst, und die Transaktion wird zurückgesetzt. | ||
| Unidirektional | ✔️ | Ja | Versucht, die Nachricht an einen Sicherungsendpunkt erneut zu senden. Nachdem die Nachricht erfolgreich empfangen wurde, schließen Sie alle Empfangskontexte ab. Wenn die Nachricht von einem Endpunkt nicht erfolgreich empfangen wurde, schließen Sie den Empfangskontext nicht ab. Wenn diese Nachricht als Multicast gesendet wird, wird der Empfangskontext nur abgeschlossen, wenn die Nachricht erfolgreich von mindestens einem Endpunkt (primär oder Backup) empfangen wurde. Wenn keiner der Endpunkte in einem der Multicastpfade die Nachricht erfolgreich empfängt, schließen Sie den Empfangskontext nicht ab. |
||
| Unidirektional | ✔️ | ✔️ | Ja | Beenden Sie die vorherige Transaktion, erstellen Sie eine neue Transaktion, und senden Sie alle Nachrichten erneut. Nachrichten, bei denen ein Fehler aufgetreten ist, werden an ein Sicherungsziel übertragen. Nachdem eine Transaktion erstellt wurde, bei der alle Übertragungen erfolgreich sind, schließen Sie die Empfangskontexte ab und führen Sie die Transaktion aus. |
|
| Unidirektional | ✔️ | Ja | Versucht, die Nachricht an einen Sicherungsendpunkt erneut zu senden. In einem Multicastszenario werden nur die Nachrichten in einer Sitzung, bei denen ein Fehler aufgetreten ist, oder in einer Sitzung, deren Sitzungsabschluss fehlgeschlagen ist, an Sicherungsziele erneut gesendet. | ||
| Unidirektional | ✔️ | ✔️ | Nein | Eine Ausnahme wird ausgelöst, und die Transaktion wird zurückgesetzt. | |
| Unidirektional | ✔️ | ✔️ | Ja | Versucht, die Nachricht an einen Sicherungsendpunkt erneut zu senden. Nachdem alle Nachrichten fehlerfrei gesendet wurden, zeigt die Sitzung an, dass keine weiteren Nachrichten vorhanden sind, und der Routingdienst schließt erfolgreich alle ausgehenden Sitzungskanäle. Alle Empfangskontexte werden abgeschlossen, und der eingehende Sitzungskanal wird geschlossen. | |
| Unidirektional | ✔️ | ✔️ | ✔️ | Ja | Abbrechen der aktuellen Transaktion und Erstellen einer neuen Transaktion. Senden Sie alle vorherigen Nachrichten der Sitzung neu. Nachdem eine Transaktion erstellt wurde, in der alle Nachrichten erfolgreich gesendet wurden und die Sitzung keine weiteren Nachrichten anzeigt, werden alle ausgehenden Sitzungskanäle geschlossen, Empfangskontexte werden mit der Transaktion abgeschlossen, der eingehende Sitzungskanal wird geschlossen, und die Transaktion wird zugesichert. Wenn die Sitzungen per Multicast gesendet werden, werden die fehlerfreien Nachrichten an dasselbe Ziel wie zuvor gesendet, und Nachrichten, bei denen ein Fehler aufgetreten ist, werden an Sicherungsziele gesendet. |
| Bidirektional | Ja | An ein Sicherungsziel senden. Nachdem ein Kanal eine Antwortnachricht zurückgegeben hat, geben Sie die Antwort an den ursprünglichen Client zurück. | |||
| Bidirektional | ✔️ | Ja | Senden Sie alle Nachrichten im Kanal an ein Sicherungsziel. Nachdem ein Kanal eine Antwortnachricht zurückgegeben hat, geben Sie die Antwort an den ursprünglichen Client zurück. | ||
| Bidirektional | ✔️ | Nein | Eine Ausnahme wird ausgelöst, und die Transaktion wird zurückgesetzt. | ||
| Bidirektional | ✔️ | ✔️ | Nein | Eine Ausnahme wird ausgelöst, und die Transaktion wird zurückgesetzt. | |
| Doppelhaus | Nein | Die Nicht-Sitzungsduplexkommunikation wird derzeit nicht unterstützt. | |||
| Doppelhaus | ✔️ | Ja | An ein Sicherungsziel senden. |
Gastgeberrolle
Da der Routingdienst als WCF-Dienst implementiert ist, muss er entweder in einer Anwendung selbst gehostet oder von IIS oder WAS gehostet werden. Es wird empfohlen, dass der Routingdienst entweder in IIS, WAS oder einer Windows-Dienstanwendung gehostet wird, um die in diesen Hostingumgebungen verfügbaren Features für die automatische Start- und Lebenszyklusverwaltung zu nutzen.
Im folgenden Beispiel wird das Hosten des Routingdiensts in einer Anwendung veranschaulicht.
using (ServiceHost serviceHost =
new ServiceHost(typeof(RoutingService)))
Um den Routingdienst in IIS oder WAS zu hosten, müssen Sie entweder eine Dienstdatei (.svc) erstellen oder die konfigurationsbasierte Aktivierung des Diensts verwenden. Bei Verwendung einer Dienstdatei müssen Sie RoutingService angeben, indem Sie den Service-Parameter verwenden. Das folgende Beispiel enthält eine Beispieldienstdatei, die zum Hosten des Routingdiensts mit IIS oder WAS verwendet werden kann.
<%@ ServiceHost Language="C#" Debug="true" Service="System.ServiceModel.Routing.RoutingService,
System.ServiceModel.Routing, version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" %>
Routingdienst und Identitätswechsel
Der WCR-Routingdienst kann mit dem Identitätswechsel sowohl zum Senden als auch zum Empfangen von Nachrichten verwendet werden. Alle üblichen Windows-Einschränkungen des Identitätswechsels sind gültig. Wenn es beim Schreiben eines eigenen Diensts erforderlich ist, Dienst- oder Kontoberechtigungen für die Verwendung des Identitätswechsels einzurichten, müssen Sie dieselben Schritte ausführen, um den Identitätswechsel mit dem Routingdienst zu verwenden. Weitere Informationen finden Sie unter Delegierung und Identitätswechsel.
Der Identitätswechsel mit dem Routingdienst erfordert entweder die Verwendung des ASP.NET-Identitätswechsels (im ASP.NET-Kompatibilitätsmodus) oder die Verwendung von Windows-Anmeldeinformationen, die konfiguriert wurden, um den Identitätswechsel zu ermöglichen. Weitere Informationen zum ASP.NET Kompatibilitätsmodus finden Sie unter WCF-Dienste und ASP.NET.
Warnung
Der WCF-Routingdienst unterstützt keinen Identitätswechsel mit Standardauthentifizierung.
Um den ASP.NET-Identitätswechsel mit dem Routingdienst zu verwenden, aktivieren Sie den ASP.NET-Kompatibilitätsmodus für die Hostingumgebung des Diensts. Der Routingdienst ist bereits für die Verwendung des ASP.NET-Kompatibilitätsmodus gekennzeichnet, und der Identitätswechsel wird automatisch aktiviert. Der Identitätswechsel ist die einzige unterstützte Verwendung der ASP.NET-Integration mit dem Routingdienst.
Um die Windows-Anmeldeinformationen-Impersonation im Routingdienst zu verwenden, müssen Sie sowohl die Anmeldeinformationen als auch den Dienst konfigurieren. Das Objekt für Clientanmeldeinformationen (WindowsClientCredential, auf das von der ChannelFactory zugegriffen werden kann) definiert eine AllowedImpersonationLevel-Eigenschaft, die festgelegt werden muss, um den Identitätswechsel zu ermöglichen. Schließlich müssen Sie für den Dienst das ServiceAuthorizationBehavior Verhalten konfigurieren, um ImpersonateCallerForAllOperations auf true festzulegen. Der Routingdienst verwendet dieses Flag, um zu entscheiden, ob die Clients zum Weiterleiten von Nachrichten mit aktiviertem Identitätswechsel erstellt werden sollen.