WS-Discovery med WCF 4


Att WCF 4 nu kommer med stöd för WS-Discovery protokollet tycker jag är en riktig höjdare. Protokollet i sig är ingen nyhet men det är först i .NET 4.0 som WCF-stacken levereras med detta direkt "från fabrik".

Med hjälp av WS-Discovery kan tjänster och konsumenter kommunicera och hitta varandra utan något behov av tjänsteregister eller liknande.

Hur fungerar det då?

I mitt exempel (som jag lånat från WS-Discovery specifikationsdokumentet) har jag en konsument som söker efter en skrivare. Förfrågan skickas ut på nätverket och till svar får jag en lista med Endpoints som påstår sig implementera det kontrakt jag specificerat i min förfrågan (Probe).

discovery-probe

Det första jag måste göra för att få fart i detta är att skapa två sk DiscoveryEndpoints; en på konsumentsidan och en på tjänstesidan. Denna typ av Endpoint finns med i WCF 4's uppsättning av sk Standard Endpoints varför jag endast behöver lägga till ett Endpoint-element och sätta dess nytillkomna Kind egenskap i konfiguration. Adresser , Bindningar och Kontrakt (som vi är vana vid att definiera på en Endpoint) hanterar WCF åt oss på Standard Endpoints.

<endpoint kind="udpDiscoveryEndpoint" />

Ovan: Endpoint-definition tjänst.

var discoClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new FindCriteria(typeof(IPrintService));
var result = discoClient.Find(criteria);

var numberOfPrintersFound = result.Endpoints.Count;

Ovan: Konsument skickar förfrågan efter en skrivare

Oftast är det ju också som så att jag söker efter en mer specifik skrivare. Vi har trots allt sju våningsplan på vårat kontor i Kista och det vore ju angenämt om min utskrift kunde hamna på en skrivare på det våningsplan jag anger. Ibland söker jag även efter en skrivare som klarar att skriva ut i färg.

Denna typ av sökkriterier definieras i form av Scopes och Extensions. Dessa egenskaper kan tjänsterna exponera och när jag skickar en förfrågan om tjänst som uppfyller mina ställda kriterier så kommer jag endast få svar från tjänster som har matchande egenskaper definierade.

I nedan exempel påstår skrivaren att den är lokaliserad på plan 3...

<endpointBehaviors>
  <behavior>
    <endpointDiscovery>
      <scopes>
        <add scope="ldap:///ou=floor3,ou=kista,o=chrislof-example,c=local"/>
      </scopes>
    </endpointDiscovery>
  </behavior>
</endpointBehaviors>

... Och konsumenten adderar ett Scope med samma värde i sin förfrågan.

var criteria = new FindCriteria(typeof(IPrintService));
criteria.Scopes.Add(new Uri("ldap:///ou=floor3,ou=kista,o=chrislof-example,c=local"));

I WS-Discovery finns det också funktionalitet definierad så att tjänster kan notifiera varandra om sin existens (Announce). Det handlar i praktiken om att skicka ut notifiering om "Hej! Jag har startat upp nu - och jag finns på denna adress" alternativt "Vill bara tala om att jag stängs ned nu...". Även detta är i WCF 4 implementerat med Standard Endpoints, vilket gör det väldigt enkelt att anamma.

discovery-announce

Den lilla detaljen som jag måste beaktas är att Announcement-Endpointen måste definieras genom ett ServiceDiscovery-behavior. Men detta är allt som jag behöver göra på tjänstesidan.

<serviceBehaviors>
  <behavior>
    <serviceDiscovery>
      <announcementEndpoints>
        <endpoint kind="udpAnnouncementEndpoint" />
      </announcementEndpoints>
    </serviceDiscovery>
  </behavior>
</serviceBehaviors>

På konsumentsidan behöver jag instansiera AnnouncementService och lyssna på dess Events OnlineAnnouncementReceived och OfflineAnnouncementReceived för att kunna agera därefter. Jag behöver även exponera denna tjänst med en Announcement Standard Endpoint.

Konsument och Tjänst - och nu en Konsument som exponerar en Tjänst? Nja - Tjänster kan också vara konsumenter samt vice versa.

var announcementService = new AnnouncementService();

announcementService.OfflineAnnouncementReceived += (o, e) => 
    Console.WriteLine("Bye {0}", e.AnnouncementMessage.EndpointDiscoveryMetadata.Address);

announcementService.OnlineAnnouncementReceived += (o, e) =>
    Console.WriteLine("Hi! {0}", e.AnnouncementMessage.EndpointDiscoveryMetadata.Address);

Så om jag knyter an till mitt tidigare exempel med skrivaren - så får jag i detta fall en notifiering om att skrivaren stängs av.

announce

Hela tiden i ovan exempel är det sk Ad Hoc Discovery (utan mellanhand) som används. Detta begränsar användandet till det lokala nätet då det är baserat på multicast meddelanden. För att möjliggöra Discovery över t ex Internet måste en sk Discovery Proxy Service implementeras. Denna tjänst är inget som vid skrivandets stund levereras färdigt utan måste implementeras manuellt med utgångspunkt från DiscoveryProxyBase. När man använder denna modell, med en Discovery Proxy , kallas det för Managed Discovery.

Att visa hur man implementerar en Discovery Proxy är utanför omfattningen av denna artikel.

Ladda ned ovan exempel här:

Comments (1)
  1. Dag says:

    Tack, det var ett mycket bra och enkelt demo. Det skall jag använda imorgon.

    /dag

Comments are closed.

Skip to main content