Delen via


Procedure: Filters gebruiken

In dit onderwerp worden de basisstappen beschreven die nodig zijn om een routeringsconfiguratie te maken die gebruikmaakt van meerdere filters. In dit voorbeeld worden berichten doorgestuurd naar twee implementaties van een calculatorservice, regularCalc en roundingCalc. Beide implementaties ondersteunen dezelfde bewerkingen; maar één service rondt alle berekeningen af op de dichtstbijzijnde gehele waarde voordat deze wordt geretourneerd. Een clienttoepassing moet kunnen aangeven of de afrondingsversie van de service moet worden gebruikt; Als er geen servicevoorkeur wordt uitgedrukt, wordt het bericht verdeeld over de twee services. De bewerkingen die door beide services worden weergegeven, zijn:

  • Toevoegen

  • Aftrekken

  • Vermenigvuldigen

  • Delen

Omdat beide services dezelfde bewerkingen implementeren, kunt u het actiefilter niet gebruiken, omdat de actie die is opgegeven in het bericht niet uniek is. In plaats daarvan moet u extra werk doen om ervoor te zorgen dat de berichten worden doorgestuurd naar de juiste eindpunten.

Unieke gegevens bepalen

  1. Omdat beide service-implementaties dezelfde bewerkingen verwerken en in wezen identiek zijn aan de gegevens die ze retourneren, zijn de basisgegevens die zijn opgenomen in berichten die vanuit clienttoepassingen worden verzonden, niet uniek genoeg, zodat u kunt bepalen hoe de aanvraag moet worden gerouteerd. Maar als de clienttoepassing een unieke headerwaarde toevoegt aan het bericht, kunt u deze waarde gebruiken om te bepalen hoe het bericht moet worden gerouteerd.

    Als in dit voorbeeld de clienttoepassing het bericht moet worden verwerkt door de afrondingscalculator, wordt er een aangepaste header toegevoegd met behulp van de volgende code:

    messageHeadersElement.Add(MessageHeader.CreateHeader("RoundingCalculator",
                                   "http://my.custom.namespace/", "rounding"));  
    

    U kunt nu het XPath-filter gebruiken om berichten voor deze koptekst te controleren en berichten met de koptekst te routeren naar de roundCalc-service.

  2. Daarnaast bevat de routeringsservice twee virtuele service-eindpunten die kunnen worden gebruikt met de filters EndpointName, EndpointAddress of PrefixEndpointAddress om binnenkomende berichten op unieke wijze te routeren naar een specifieke rekenmachine-implementatie op basis van het eindpunt waarnaar de clienttoepassing de aanvraag verzendt.

Eindpunten definiëren

  1. Wanneer u de eindpunten definieert die door de Routeringsservice worden gebruikt, moet u eerst de vorm bepalen van het kanaal dat door uw clients en services wordt gebruikt. In dit scenario gebruiken beide doelservices een aanvraag-antwoordpatroon, dus het IRequestReplyRouter wordt gebruikt. In het volgende voorbeeld worden de service-eindpunten gedefinieerd die worden weergegeven door de routeringsservice.

    <services>  
          <service behaviorConfiguration="routingConfiguration"  
                   name="System.ServiceModel.Routing.RoutingService">  
            <host>  
              <baseAddresses>  
                <add baseAddress="http://localhost/routingservice/router" />  
              </baseAddresses>  
            </host>  
            <!--Set up the inbound endpoints for the Routing Service-->  
            <!--first create the general router endpoint-->  
            <endpoint address="general"  
                      binding="wsHttpBinding"  
                      name="routerEndpoint"  
                      contract="System.ServiceModel.Routing.IRequestReplyRouter" />  
            <!--create a virtual endpoint for the regular calculator service-->  
            <endpoint address="regular/calculator"  
                      binding="wsHttpBinding"  
                      name="calculatorEndpoint"  
                      contract="System.ServiceModel.Routing.IRequestReplyRouter" />  
            <!--now create a virtual endpoint for the rounding calculator-->  
            <endpoint address="rounding/calculator"  
                      binding="wsHttpBinding"  
                      name="roundingEndpoint"  
                      contract="System.ServiceModel.Routing.IRequestReplyRouter" />  
    
          </service>  
    </services>  
    

    Met deze configuratie biedt de routeringsservice drie afzonderlijke eindpunten. Afhankelijk van runtime-keuzes verzendt de clienttoepassing berichten naar een van deze adressen. Berichten die binnenkomen bij een van de 'virtuele' service-eindpunten ('rounding/calculator' of 'regular/calculator') worden doorgestuurd naar de bijbehorende rekenmachine-implementatie. Als de clienttoepassing de aanvraag niet naar een bepaald eindpunt verzendt, wordt het bericht geadresseerd aan het algemene eindpunt. Ongeacht het gekozen eindpunt kan de clienttoepassing er ook voor kiezen om de aangepaste header op te nemen om aan te geven dat het bericht moet worden doorgestuurd naar de implementatie van de afrondingscalculator.

  2. In het volgende voorbeeld worden de clienteindpunten (doel) gedefinieerd waarnaar de routeringsservice berichten routeert.

    <client>  
          <endpoint name="regularCalcEndpoint"  
                    address="net.tcp://localhost:9090/servicemodelsamples/service/"  
                    binding="netTcpBinding"  
                    contract="*" />  
    
          <endpoint name="roundingCalcEndpoint"  
                    address="net.tcp://localhost:8080/servicemodelsamples/service/"  
                    binding="netTcpBinding"  
                    contract="*" />  
    </client>  
    

    Deze eindpunten worden gebruikt in de filtertabel om het doeleindpunt aan te geven waarnaar het bericht wordt verzonden wanneer het overeenkomt met een specifiek filter.

Filters definiëren

  1. Als u berichten wilt routeren op basis van de aangepaste header RoundingCalculator die de clienttoepassing toevoegt aan het bericht, definieert u een filter dat gebruikmaakt van een XPath-query om te controleren op de aanwezigheid van deze header. Omdat deze header wordt gedefinieerd met behulp van een aangepaste naamruimte, voegt u ook een naamruimtevermelding toe waarmee een aangepast naamruimtevoorvoegsel van 'aangepast' wordt gedefinieerd dat wordt gebruikt in de XPath-query. In het volgende voorbeeld worden de benodigde routeringssectie, naamruimtetabel en XPath-filter gedefinieerd.

    <routing>  
          <!-- use the namespace table element to define a prefix for our custom namespace-->  
          <namespaceTable>  
            <add prefix="custom" namespace="http://my.custom.namespace/"/>  
          </namespaceTable>  
          <filters>  
            <!--define the different message filters-->  
            <!--define an xpath message filter to look for the custom header coming from the client-->  
            <filter name="XPathFilter" filterType="XPath"
                    filterData="/s12:Envelope/s12:Header/custom:RoundingCalculator = 'rounding'"/>  
          </filters>  
    </routing>  
    

    Dit MessageFilter zoekt naar een roundingCalculator-header in het bericht dat een waarde 'afronden' bevat. Deze header wordt door de client ingesteld om aan te geven dat het bericht moet worden gerouteerd naar de roundingCalc-service.

    Notitie

    Het voorvoegsel voor de s12-naamruimte wordt standaard gedefinieerd in de naamruimtetabel en vertegenwoordigt de naamruimte http://www.w3.org/2003/05/soap-envelope.

  2. U moet ook filters definiëren die zoeken naar berichten die zijn ontvangen op de twee virtuele eindpunten. Het eerste virtuele eindpunt is het eindpunt 'regular/calculator'. De client kan aanvragen naar dit eindpunt verzenden om aan te geven dat het bericht moet worden doorgestuurd naar de regularCalc-service. De volgende configuratie definieert een filter dat gebruikmaakt van het EndpointNameMessageFilter filter om te bepalen of het bericht is aangekomen via een eindpunt met de naam die is opgegeven in filterData.

    <!--define an endpoint name filter looking for messages that show up on the virtual regular calculator endpoint-->  
    <filter name="EndpointNameFilter" filterType="EndpointName" filterData="calculatorEndpoint"/>  
    

    Als een bericht wordt ontvangen door het service-eindpunt met de naam 'calculatorEndpoint', wordt dit filter geëvalueerd.true

  3. Definieer vervolgens een filter waarmee wordt gezocht naar berichten die naar het adres van het roundingEndpoint worden verzonden. De client kan aanvragen naar dit eindpunt verzenden om aan te geven dat het bericht moet worden doorgestuurd naar de roundingCalc-service. De volgende configuratie definieert een filter dat gebruikmaakt van het PrefixEndpointAddressMessageFilter filter om te bepalen of het bericht is aangekomen bij het eindpunt 'afronden/rekenmachine'.

    <!--define a filter looking for messages that show up with the address prefix.  The corresponds to the rounding calc virtual endpoint-->  
    <filter name="PrefixAddressFilter" filterType="PrefixEndpointAddress"  
            filterData="http://localhost/routingservice/router/rounding/"/>  
    

    Als een bericht wordt ontvangen op een adres dat begint met http://localhost/routingservice/router/rounding/ , resulteert dit filter in waar. Omdat het basisadres dat door deze configuratie wordt http://localhost/routingservice/router gebruikt en het adres dat is opgegeven voor het roundingEndpoint 'rounding/calculator' is, is http://localhost/routingservice/router/rounding/calculatorhet volledige adres dat wordt gebruikt om met dit eindpunt te communiceren, wat overeenkomt met dit filter.

    Notitie

    Het filter PrefixEndpointAddress evalueert de hostnaam niet bij het uitvoeren van een overeenkomst, omdat naar één host kan worden verwezen met behulp van een verscheidenheid aan hostnamen die mogelijk allemaal geldige manieren zijn om vanuit de clienttoepassing naar de host te verwijzen. Alle volgende kunnen bijvoorbeeld verwijzen naar dezelfde host:

    • localhost
    • 127.0.0.1
    • www.contoso.com
    • ContosoWeb01
  4. Het laatste filter moet ondersteuning bieden voor de routering van berichten die binnenkomen op het algemene eindpunt zonder de aangepaste header. Voor dit scenario moeten de berichten wisselen tussen de reguliereCalc- en roundingCalc-services. Ter ondersteuning van de round robin-routering van deze berichten gebruikt u een aangepast filter waarmee één filterexemplaren overeenkomen voor elk verwerkt bericht. Hieronder worden twee exemplaren van een RoundRobinMessageFilter gedefinieerd, die zijn gegroepeerd om aan te geven dat ze tussen elkaar moeten wisselen.

    <!-- Set up the custom message filters.  In this example,   
         we'll use the example round robin message filter,   
         which alternates between the references-->  
    <filter name="RoundRobinFilter1" filterType="Custom"  
                    customType="CustomFilterAssembly.RoundRobinMessageFilter, CustomFilterAssembly"  
                    filterData="group1"/>  
    <filter name="RoundRobinFilter2" filterType="Custom"  
                    customType="CustomFilterAssembly.RoundRobinMessageFilter, CustomFilterAssembly"  
                    filterData="group1"/>  
    

    Tijdens de runtime wisselt dit filtertype af tussen alle gedefinieerde filterexemplaren van dit type die zijn geconfigureerd als dezelfde groep in één verzameling. Dit zorgt ervoor dat berichten die door dit aangepaste filter worden verwerkt, wisselen tussen retourneren true voor RoundRobinFilter1 en RoundRobinFilter2.

Filtertabellen definiëren

  1. Als u de filters wilt koppelen aan specifieke clienteindpunten, moet u deze in een filtertabel plaatsen. In dit voorbeeldscenario worden ook instellingen voor filterprioriteit gebruikt. Dit is een optionele instelling waarmee u de volgorde kunt aangeven waarin filters worden verwerkt. Als er geen filterprioriteit is opgegeven, worden alle filters tegelijkertijd geëvalueerd.

    Notitie

    Wanneer u een filterprioriteit opgeeft, kunt u de volgorde bepalen waarin filters worden verwerkt, kan dit de prestaties van de routeringsservice nadelig beïnvloeden. Bouw, indien mogelijk, filterlogica zodat het gebruik van filterprioriteiten niet vereist is.

    Hieronder wordt de filtertabel gedefinieerd en wordt het eerder gedefinieerde XPathFilter toegevoegd aan de tabel met een prioriteit van 2. Deze vermelding geeft ook aan dat als het XPathFilter bericht overeenkomt met het bericht, het bericht wordt doorgestuurd naar de roundingCalcEndpoint.

    <routing>  
    ...      <filters>  
    ...      </filters>  
          <filterTables>  
            <table name="filterTable1">  
              <entries>  
                <!--add the filters to the message filter table-->  
                <!--first look for the custom header, and if we find it,  
                    send the message to the rounding calc endpoint-->  
                <add filterName="XPathFilter" endpointName="roundingCalcEndpoint" priority="2"/>  
              </entries>  
            </table>  
          </filterTables>  
    </routing>  
    

    Wanneer u een filterprioriteit opgeeft, worden de filters met de hoogste prioriteit eerst geëvalueerd. Als een of meer filters op een bepaald prioriteitsniveau overeenkomen, worden er geen filters op lagere prioriteitsniveaus geëvalueerd. Voor dit scenario is 2 de hoogste prioriteit opgegeven en dit is de enige filtervermelding op dit niveau.

  2. Filtervermeldingen zijn gedefinieerd om te controleren of een bericht op een specifiek eindpunt wordt ontvangen door de naam van het eindpunt of het adresvoorvoegsel te controleren. De volgende vermeldingen voegen beide filtervermeldingen toe aan de filtertabel en koppelen deze aan de doeleindpunten waarnaar het bericht wordt gerouteerd. Deze filters zijn ingesteld op een prioriteit van 1 om aan te geven dat ze alleen moeten worden uitgevoerd als het vorige XPath-filter niet overeenkomt met het bericht.

    <!--if the header wasn't there, send the message based on which virtual endpoint it arrived at-->  
    <!--we determine this through the endpoint name, or through the address prefix-->  
    <add filterName="EndpointNameFilter" endpointName="regularCalcEndpoint" priority="1"/>  
    <add filterName="PrefixAddressFilter" endpointName="roundingCalcEndpoint" priority="1"/>  
    

    Omdat deze filters een filterprioriteit van 1 hebben, worden ze alleen geëvalueerd als het filter op prioriteitsniveau 2 niet overeenkomt met het bericht. Omdat beide filters hetzelfde prioriteitsniveau hebben, worden ze tegelijkertijd geëvalueerd. Omdat beide filters elkaar wederzijds uitsluiten, is het mogelijk dat slechts één of de andere filters overeenkomen met een bericht.

  3. Als een bericht niet overeenkomt met een van de vorige filters, is het bericht ontvangen via het algemene service-eindpunt en bevat geen headerinformatie die aangeeft waar het moet worden gerouteerd. Deze berichten moeten worden verwerkt door het aangepaste filter, waarmee de taakverdeling tussen de twee rekenmachineservices wordt verdeeld. In het volgende voorbeeld ziet u hoe u de filtervermeldingen toevoegt aan de filtertabel; elk filter is gekoppeld aan een van de twee doeleindpunten.

    <!--if none of the other filters have matched,   
        this message showed up on the default router endpoint,   
        with no custom header-->  
    <!--round robin these requests between the two services-->  
    <add filterName="RoundRobinFilter1" endpointName="regularCalcEndpoint" priority="0"/>  
    <add filterName="RoundRobinFilter2" endpointName="roundingCalcEndpoint" priority="0"/>  
    

    Omdat deze vermeldingen een prioriteit van 0 opgeven, worden ze alleen geëvalueerd als er geen filter met een hogere prioriteit overeenkomt met het bericht. Omdat beide van dezelfde prioriteit zijn, worden ze ook tegelijkertijd geëvalueerd.

    Zoals eerder vermeld, evalueert het aangepaste filter dat door deze filterdefinities wordt gebruikt, slechts één of de andere, zoals true voor elk ontvangen bericht. Omdat er slechts twee filters zijn gedefinieerd met dit filter, met dezelfde opgegeven groepsinstelling, is het effect dat de routeringsservice wisselt tussen het verzenden naar het reguliereCalcEndpoint en het afronden vanCalcEndpoint.

  4. Als u berichten wilt evalueren op basis van de filters, moet de filtertabel eerst worden gekoppeld aan de service-eindpunten die worden gebruikt om berichten te ontvangen. In het volgende voorbeeld ziet u hoe u de routeringstabel koppelt aan de service-eindpunten met behulp van het routeringsgedrag:

    <behaviors>  
      <!--default routing service behavior definition-->  
      <serviceBehaviors>  
        <behavior name="routingConfiguration">  
          <routing filterTableName="filterTable1" />  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>  
    

Opmerking

Hier volgt een volledige lijst van het configuratiebestand.

<?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 endpoints for the Routing Service-->  
        <!--first create the general router endpoint-->  
        <endpoint address="general"  
                  binding="wsHttpBinding"  
                  name="routerEndpoint"  
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />  
        <!--create a virtual endpoint for the regular calculator service-->  
        <endpoint address="regular/calculator"  
                  binding="wsHttpBinding"  
                  name="calculatorEndpoint"  
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />  
        <!--now create a virtual endpoint for the rounding calculator-->  
        <endpoint address="rounding/calculator"  
                  binding="wsHttpBinding"  
                  name="roundingEndpoint"  
                  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 endpoints-->  
      <endpoint name="regularCalcEndpoint"  
                address="net.tcp://localhost:9090/servicemodelsamples/service/"  
                binding="netTcpBinding"  
                contract="*" />  
  
      <endpoint name="roundingCalcEndpoint"  
                address="net.tcp://localhost:8080/servicemodelsamples/service/"  
                binding="netTcpBinding"  
                contract="*" />  
    </client>  
    <routing>  
      <!-- use the namespace table element to define a prefix for our custom namespace-->  
      <namespaceTable>  
        <add prefix="custom" namespace="http://my.custom.namespace/"/>  
      </namespaceTable>  
      <filters>  
        <!--define the different message filters-->  
        <!--define an xpath message filter to look for the custom header coming from the client-->  
        <filter name="XPathFilter" filterType="XPath" filterData="/s12:Envelope/s12:Header/custom:RoundingCalculator = 'rounding'"/>  
  
        <!--define an endpoint name filter looking for messages that show up on the virtual regular calculator endpoint-->  
        <filter name="EndpointNameFilter" filterType="EndpointName" filterData="calculatorEndpoint"/>  
  
        <!--define a filter looking for messages that show up with the address prefix.  The corresponds to the rounding calc virtual endpoint-->  
        <filter name="PrefixAddressFilter" filterType="PrefixEndpointAddress" filterData="http://localhost/routingservice/router/rounding/"/>  
  
        <!--Set up the custom message filters.  In this example, we'll use the example round robin message filter, which alternates between the references-->  
        <filter name="RoundRobinFilter1" filterType="Custom" customType="CustomFilterAssembly.RoundRobinMessageFilter, CustomFilterAssembly" filterData="group1"/>  
        <filter name="RoundRobinFilter2" filterType="Custom" customType="CustomFilterAssembly.RoundRobinMessageFilter, CustomFilterAssembly" filterData="group1"/>  
      </filters>  
      <filterTables>  
        <table name="filterTable1">  
          <entries>  
            <!--add the filters to the message filter table-->  
            <!--first look for the custom header, and if we find it, send the message to the rounding calc endpoint-->  
            <add filterName="XPathFilter" endpointName="roundingCalcEndpoint" priority="2"/>  
  
            <!--if the header wasn't there, send the message based on which virtual endpoint it arrived at-->  
            <!--we determine this through the endpoint name, or through the address prefix-->  
            <add filterName="EndpointNameFilter" endpointName="regularCalcEndpoint" priority="1"/>  
            <add filterName="PrefixAddressFilter" endpointName="roundingCalcEndpoint" priority="1"/>  
  
            <!--if none of the other filters have matched, this message showed up on the default router endpoint, with no custom header-->  
            <!--round robin these requests between the two services-->  
            <add filterName="RoundRobinFilter1" endpointName="regularCalcEndpoint" priority="0"/>  
            <add filterName="RoundRobinFilter2" endpointName="roundingCalcEndpoint" priority="0"/>  
          </entries>  
        </table>  
      </filterTables>  
    </routing>  
  </system.serviceModel>  
</configuration>  

Zie ook