Instrukcje: Aktualizacja dynamiczna
W tym temacie opisano podstawowe kroki wymagane do utworzenia i dynamicznego aktualizowania konfiguracji routingu. W tym przykładzie początkowa konfiguracja routingu jest uzyskiwana z pliku konfiguracji i kieruje wszystkie komunikaty do usługi zwykłego kalkulatora obliczeń; jednak programowo jest aktualizowany w celu zmiany docelowego punktu końcowego usługi roundingCalc.
Uwaga
W wielu implementacjach konfiguracja będzie w pełni dynamiczna i nie będzie polegać na konfiguracji domyślnej; Jednak istnieją pewne scenariusze, takie jak ten w tym temacie, gdzie pożądane jest, aby po uruchomieniu usługi miał domyślny stan konfiguracji.
Uwaga
Aktualizacje dynamiczne są wykonywane tylko w pamięci i nie powodują modyfikacji plików konfiguracji.
Zarówno regularCalc, jak i roundingCalc obsługują te same operacje dodawania, odejmowania, mnożenia i dzielenia; jednak funkcja RoundingCalc zaokrągla wszystkie obliczenia do najbliższej wartości całkowitej przed zwróceniem. Plik konfiguracji służy do konfigurowania usługi w celu kierowania wszystkich komunikatów do regularnej usługiCalc. Po uruchomieniu ApplyConfiguration usługi routingu jest używana do ponownej konfiguracji usługi w celu kierowania komunikatów do usługi roundingCalc.
Implementowanie konfiguracji początkowej
Utwórz podstawową konfigurację usługi routingu, określając punkty końcowe usługi uwidocznione przez usługę. W poniższym przykładzie zdefiniowano pojedynczy punkt końcowy usługi, który będzie używany do odbierania komunikatów. Definiuje również punkt końcowy klienta, który będzie używany do wysyłania komunikatów do zwykłego obliczania.
<services> <service behaviorConfiguration="routingConfiguration" name="System.ServiceModel.Routing.RoutingService"> <host> <baseAddresses> <add baseAddress="http://localhost/routingservice/router" /> </baseAddresses> </host> <!--Set up the inbound endpoint for the Routing Service--> <endpoint address="calculator" binding="wsHttpBinding" name="routerEndpoint" contract="System.ServiceModel.Routing.IRequestReplyRouter" /> </service> </services> <client> <!--set up the destination endpoint--> <endpoint name="regularCalcEndpoint" address="net.tcp://localhost:9090/servicemodelsamples/service/" binding="netTcpBinding" contract="*" /> </client>
Zdefiniuj filtr używany do kierowania komunikatów do docelowych punktów końcowych. W tym przykładzie filtr MatchAll służy do kierowania wszystkich komunikatów do zdefiniowanego wcześniej punktu regularnegoCalcEndpoint. W poniższym przykładzie zdefiniowano tabelę filtru i filtru.
<filters> <!--define the message filter--> <filter name="MatchAllFilter" filterType="MatchAll"/> </filters> <filterTables> <filterTable name="filterTable1"> <!--add the filter to the message filter table--> <add filterName="MatchAllFilter" endpointName="regularCalcEndpoint"/> </filterTable> </filterTables>
Aby ocenić komunikaty przychodzące względem filtrów zawartych 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 punktem końcowym usługi.
<behaviors> <!--default routing service behavior definition--> <serviceBehaviors> <behavior name="routingConfiguration"> <routing filterTableName="filterTable1" /> </behavior> </serviceBehaviors> </behaviors>
Implementowanie konfiguracji dynamicznej
Dynamiczna konfiguracja usługi routingu może być wykonywana tylko w kodzie, tworząc nową RoutingConfiguration i używając polecenia ApplyConfiguration , aby zastąpić bieżącą konfigurację. W tym przykładzie usługa routingu jest hostowana samodzielnie w aplikacji konsolowej. Po uruchomieniu aplikacji można zmodyfikować konfigurację routingu, wprowadzając "regularne" lub "zaokrąglanie" w oknie konsoli, aby skonfigurować docelowy punkt końcowy, do którego są kierowane komunikaty; regularCalc po wprowadzeniu elementu "regular", w przeciwnym razie zaokrąglanie obliczania po wprowadzeniu zaokrąglania.
Aby obsługiwać usługę routingu, należy dodać następujące
using
dyrektywy.using System; using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.ServiceModel.Routing;
Poniższy kod służy do samodzielnego hostowania usługi routingu jako aplikacji konsolowej. Spowoduje to zainicjowanie usługi routingu przy użyciu konfiguracji opisanej w poprzednim kroku, która znajduje się w pliku konfiguracji aplikacji. Pętla while zawiera kod używany do zmiany konfiguracji routingu.
// Host the service within this EXE console application. public static void Main() { // Create a ServiceHost for the CalculatorService type. using (ServiceHost serviceHost = new ServiceHost(typeof(RoutingService))) { // Open the ServiceHost to create listeners // and start listening for messages. Console.WriteLine("The Routing Service configured, opening...."); serviceHost.Open(); Console.WriteLine("The Routing Service is now running."); Console.WriteLine("Type 'quit' to terminate router."); Console.WriteLine("<ENTER> to change routing configuration."); while (Console.ReadLine() != "quit") { .... } } }
Aby dynamicznie aktualizować konfigurację routingu, należy utworzyć nową konfigurację routingu. Musi zawierać wszystkie punkty końcowe, filtry i tabele filtrów wymagane dla nowej konfiguracji routingu, ponieważ całkowicie zastąpi istniejącą konfigurację routingu. Aby użyć nowej konfiguracji routingu, należy wywołać ApplyConfiguration i przekazać nową konfigurację.
Dodaj następujący kod do pętli while zdefiniowanej wcześniej, aby umożliwić ponowne skonfigurowanie usługi na podstawie danych wejściowych użytkownika.
Console.WriteLine("Enter 'regular' or 'rounding' to set the destination endpoint:"); string destEndpoint = Console.ReadLine(); // Create a new RoutingConfiguration RoutingConfiguration rc = new RoutingConfiguration(); // Determine the endpoint to configure for switch (destEndpoint) { case "regular": // Define the destination endpoint ServiceEndpoint regularCalc = new ServiceEndpoint( ContractDescription.GetContract(typeof(IRequestReplyRouter)), new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:9090/servicemodelsamples/service/")); // Create a MatchAll filter and add to the filter table rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { regularCalc }); // Use ApplyConfiguration to update the Routing Service serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc); Console.WriteLine("Applied new routing configuration."); break; case "rounding": // Define the destination endpoint ServiceEndpoint roundingCalc = new ServiceEndpoint( ContractDescription.GetContract(typeof(IRequestReplyRouter)), new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:8080/servicemodelsamples/service/")); // Create a MatchAll filter and add to the filter table rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { roundingCalc }); // Use ApplyConfiguration to update the Routing Service serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc); Console.WriteLine("Applied new routing configuration."); break; default: Console.WriteLine("Incorrect value entered, no change."); break; }
Uwaga
Ponieważ metoda dostarczania nowego routinguConfiguration jest zawarta w rozszerzeniu usługi RoutingExtension, nowe obiekty RoutingConfiguration można udostępnić w dowolnym miejscu w modelu rozszerzalności programu WCF, który ma lub może uzyskać odwołanie do serviceHost lub ServiceExtensions (na przykład w innej usłudze ServiceExtension).
Przykład 1
Poniżej przedstawiono pełną listę aplikacji konsolowej używanej w tym przykładzie:
//-----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All Rights Reserved.
//-----------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Routing;
namespace Microsoft.Samples.AdvancedFilters
{
public class Router
{
// Host the service within this EXE console application.
public static void Main()
{
// Create a ServiceHost for the CalculatorService type.
using (ServiceHost serviceHost =
new ServiceHost(typeof(RoutingService)))
{
// Open the ServiceHost to create listeners
// and start listening for messages.
Console.WriteLine("The Routing Service configured, opening....");
serviceHost.Open();
Console.WriteLine("The Routing Service is now running.");
Console.WriteLine("Type 'quit' to terminate router.");
Console.WriteLine("<ENTER> to change routing configuration.");
while (Console.ReadLine() != "quit")
{
Console.WriteLine("Enter 'regular' or 'rounding' to set the destination endpoint:");
string destEndpoint = Console.ReadLine();
// Create a new RoutingConfiguration
RoutingConfiguration rc = new RoutingConfiguration();
// Determine the endpoint to configure for
switch (destEndpoint)
{
case "regular":
// Define the destination endpoint
ServiceEndpoint regularCalc = new ServiceEndpoint(
ContractDescription.GetContract(typeof(IRequestReplyRouter)),
new NetTcpBinding(),
new EndpointAddress("net.tcp://localhost:9090/servicemodelsamples/service/"));
// Create a MatchAll filter and add to the filter table
rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { regularCalc });
// Use ApplyConfiguration to update the Routing Service
serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
Console.WriteLine("Applied new routing configuration.");
break;
case "rounding":
// Define the destination endpoint
ServiceEndpoint roundingCalc = new ServiceEndpoint(
ContractDescription.GetContract(typeof(IRequestReplyRouter)),
new NetTcpBinding(),
new EndpointAddress("net.tcp://localhost:8080/servicemodelsamples/service/"));
// Create a MatchAll filter and add to the filter table
rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { roundingCalc });
// Use ApplyConfiguration to update the Routing Service
serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
Console.WriteLine("Applied new routing configuration.");
break;
default:
Console.WriteLine("Incorrect value entered, no change.");
break;
}
}
}
}
}
}
Przykład 2
Poniżej znajduje się pełna lista pliku konfiguracji używanego w tym przykładzie:
<?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/router" />
</baseAddresses>
</host>
<!--Set up the inbound endpoint for the Routing Service-->
<endpoint address="calculator"
binding="wsHttpBinding"
name="routerEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
</service>
</services>
<behaviors>
<!--default routing service behavior definition-->
<serviceBehaviors>
<behavior name="routingConfiguration">
<routing filterTableName="filterTable1" />
</behavior>
</serviceBehaviors>
</behaviors>
<client>
<!--set up the destination endpoint-->
<endpoint name="regularCalcEndpoint"
address="net.tcp://localhost:9090/servicemodelsamples/service/"
binding="netTcpBinding"
contract="*" />
</client>
<routing>
<filters>
<!--define the message filter-->
<filter name="MatchAllFilter" filterType="MatchAll"/>
</filters>
<filterTables>
<filterTable name="filterTable1">
<!--add the filter to the message filter table-->
<add filterName="MatchAllFilter" endpointName="regularCalcEndpoint"/>
</filterTable>
</filterTables>
</routing>
</system.serviceModel>
</configuration>