Routing med WCF 4

Att införa en eller flera sk Message Routers i sin tjänsteorienterade lösning görs av olika anledningar. Vanligtvis rör det sig om mer avancerade behov som att kunna brygga mellan protokoll och transport sätt, versionshantera kontrakt, centraliserad säkerhetshantering med mera. Den grundläggande förmågan som Routern har för att möjliggöra allt detta är att inspektera inkommande meddelande och sedan skicka det vidare till definierad mottagare baserat på ett regelverk.

WCF 4 tillhandahåller en färdig Routing-tjänst - Det du behöver göra är att konfigurera den efter dina behov.

Content Based Routing

Som jag skrev ovan bygger Routerns förmågor på att kunna skicka vidare ett inkommande meddelande till en definierad måltjänst. I mitt exempel denna gång visar jag vad som kallas för Content Based Routing – dvs inspektera meddlandekroppen (läs Body) och skicka sedan vidare meddelandet baserat på meddelandeinnehåll.

routing

Konsumenten (C) har en Proxy baserad på en ordertjänsts kontrakt (S). Istället för att ansluta till ordertjänstens ändpunkt så ansluter konsumenten till Routern (R). Routern kontrollerar om meddelandet kommer från en Premiumkund och skickar i sådant fall meddelandet vidare till en ordertjänst specifik för just Premiumkunder - 15% rabatt!. (I ett mer “riktigt” scenario skulle det kanske snarare röra sig om SLA-nivå eller liknande istället för en så enkel sak som rabatt.)

Det första som behöver göras är naturligtvis att exponera Routing-tjänsten. Det finns ett par olika kontrakt att välja på beroende på det kommunikationsmönster du önskar – Message Exchange Pattern. I detta fall använder jag IRequestReplyRouter. Implementationen RoutingService är densamma för alla tillgängliga kontrakt.

 <services>
  <service behaviorConfiguration="routing" name="System.ServiceModel.Routing.RoutingService">
    <host>
      <baseAddresses>
        <add baseAddress="https://localhost:8080/router"/>
      </baseAddresses>
    </host>
    <endpoint
      name="basic"
      address="basic-request-reply"
      binding="basicHttpBinding"
      contract="System.ServiceModel.Routing.IRequestReplyRouter"/>
  </service>
</services>

Nästa steg är att definiera de ändpunkter som Routern skall kunna skicka vidare meddelanden till.

 <client>
  <endpoint
    name="premiumCustomer"
    address="net.tcp://localhost:8091/orders/premium-customer"
    binding="netTcpBinding"
    contract="*"/>
  <endpoint
    name="ordinaryCustomer"
    address="https://localhost:8090/orders/ordinary-customer"
    binding="basicHttpBinding"
    contract="*"/>
</client>

Så långt är det inga konstigheter – Det är nu det balla börjar på riktigt.

Hjärtat i Routing-tjänsten är vad som kallas Filter Tables och Filters. Det är helt enkelt där jag definierar regelverket för hur meddelanden skall tolkas och skickas vidare. Jag vill i mitt exempel genomsöka meddelandekroppen efter kundnamnet “VS2010” och agera därefter. För att göra det använder jag filtertypen XPath.Det finns även här ett antal alternativ.

 <routing>
  <namespaceTable>
    <add prefix="c" namespace="urn:chrislof-examples"/>
  </namespaceTable>
  <filters>
    <filter name="ordinaryCustomerFilter" filterType="XPath" filterData="//c:customerName != 'VS2010'"/>
    <filter name="premiumCustomerFilter" filterType="XPath" filterData="//c:customerName = 'VS2010'"/>
  </filters>
  <filterTables>
    <filterTable name="filterTable">
      <add filterName="ordinaryCustomerFilter" endpointName="ordinaryCustomer"/>
      <add filterName="premiumCustomerFilter" endpointName="premiumCustomer"/>
    </filterTable>
  </filterTables>
</routing>

I filtertabellen definierar jag vilken ändpunkt meddelandet skall skickas vidare till om specificerat filter returnerar en match.

Dags att provköra!

Jag tycker mig behöva en ny Laptop och lägger därmed en order på en ny.

Place order

Routern anser inte att jag är en Premiumkund och skickar således ordern vidare till OrdinaryOrderService.

image

När jag istället beställer en Server i namnet VS2010 skickar Routern beställningen till PremiumOrderService och ger mig därmed 15% rabatt.

Place order

image

Avslutningsvis

Precis som med Discovery är ovan möjligt att implementera med WCF 3.x. Ett lysande exempel på det är Managed Services Engine. Det är dock nu med WCF 4 betydligt enklare att implementera flera av dessa förmågor som MSE:n besitter på egen hand.

Exemplet kan du ladda ned här. (Kräver VS2010 Beta 2)