Runtime endpoint discovery is one of the most challenging capabilities to implement in service oriented systems. Dynamically resolving service’s endpoints based on predefined criteria is a necessary functionality to interact with services which endpoint addresses change frequently. WS-Discovery is an OASIS Standard that defines a lightweight discovery mechanism for discovering services based on multicast messages. Essentially, WS-Discovery enables a service to send a Hello announcement message when it is initialized and a Bye message when is removed from the network. Clients can discover services by multicasting a Probe message to which a service can reply with a ProbeMatch message containing the information necessary to contact the service. Additionally, clients can find services that have changed endpoint by issuing a Resolve message to which respond with a ResolveMatch message.
Figure: WS-Discovery conceptual model
Contrary to other WS-* protocols, WS-Discovery has found a great adoption among the network device builders as it allows to streamline the interactions between these type of devices. For instance, a printer can use WS-Discovery to announce its presence on a network so that it can be discovered by the different applications that require printing documents. Windows Vista's contact location system is another example of a technology based on WS-Discovery.
The 4.0 release of Windows Communication Foundation includes an implementation of WS-Discovery that enables service’s endpoints as runtime discoverable artifacts. WCF enables the WS-Discovery capabilities in two fundamental models: Managed and Ad-Hoc. The managed mode assumes a centralized component called service proxy that serves as a persistent repository for all the services in a network. When a service is initialized it publishes its details to the discovery proxy so that it becomes accessible the the different clients in the network.
Contrary to the managed model, the Ad-Hoc mechanism does not rely on a centralized discovery proxy. In this model, services publish their presence in a network by multicasting announcement message that can be processed by the interested consumers. Additionally, clients can also multicast discover messages through the network in order to find a service that matches predefined criteria.
WCF's WS-Discovery managed mode will be the subject on a future post. Today we would like to illustrate the details of enabling dynamic discovery using the WS-Discovery 's Ad-Hoc model in WCF 4.0. This model is traditionally simpler to implement than the managed model although it can introduce some challenges from the management standpoint.
WCF 4.0 abstracts the WS-Discovery Ad-Hoc model using the ServiceDiscoveryBehavior which indicates that a service can be discoverable and the UdpDiscoveryEndpoint that instantiates a service endpoint that can listen for discovery requests. The remaining of this post will provide a practical example of the use of the WS-Discovery Ad-Hoc model in WCF 4.0
Let’s start with the following WCF service.
1: public class SampleService: ISampleService
3: public string Echo(string msg)
5: return msg;
10: public interface ISampleService
13: string Echo(string msg);
Figure: Sample WCF Service
In order to make the service discoverable we first need to add the ServiceDiscoveryBehavior to the service behavior’s collection. As explained previously, this behavior indicates to the WCF runtime that the service supports the WS-Discovery protocol.
1: using (ServiceHost host = new ServiceHost(typeof(SampleService), new Uri(base uri...)))
4: host.AddServiceEndpoint(typeof(ISampleService), new BasicHttpBinding(), String.Empty);
5: ServiceDiscoveryBehavior discoveryBehavior= new ServiceDiscoveryBehavior();
Figure: Adding the service discovery behavior
The next step is to add the UdpDiscoveryEndpoint to the list of service endpoints so that our service can start listening for WS-Discovery messages.
1: host.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Figure: Adding an UDP discovery endpoint
At this point our service is ready to receive and interpret WS-Discovery messages from the different clients on the network. However those clients are not yet aware of the existence of the service given that this one hasn’t published the Hello announcement message. We can accomplish this by simply adding a new UdpAnnoucement endpoint to the list of service endpoints.
1: discoveryBehavior.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint());
Figure: Adding an UDP announcement endpoint
In order to dynamically discover services using the Ad-Hoc model, a WCF client instantiates a DiscoveryClient that uses discovery endpoint specifying where to send Probe or Resolve messages. The client then calls Find that specifies search criteria within a FindCriteria instance. If matching services are found, Find returns a collection of EndpointDiscoveryMetadata. The following code illustrates that concept.
1: DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
2: FindResponse discoveryResponse= discoveryClient.Find(new FindCriteria(typeof(ISampleService)));
3: EndpointAddress address = discoveryResponse.Endpoints.Address;
5: SampleServiceClient service = new SampleServiceClient(new BasicHttpBinding(), address);
6: service.Echo("WS-Discovery test");
Figure: WCF WS-Discovery client
The WCF implementation of the WS-Discovery Ad-Hoc model presents various aspects that I think are worth highlighting. First, WCF uses specialized discovery and announcement endpoints to process WS-Discovery messages isolating them from the service’s messages. Additionally, the use of service behaviors allow developers to incorporate the WS-Discovery capabilities as they are required without interfering with the normal service functioning. Finally, WCF clients can simply use the discovery client to dynamically resolve the service endpoint without having to make major modifications to its business logic.
We will cover the WS-Discovery managed mode in a future post.