WCF Discovery 개요
Discovery API는 WS-Discovery 프로토콜을 사용한 웹 서비스의 동적 게시 및 검색을 위한 통합 프로그래밍 모델을 제공합니다. 이러한 API를 통해 서비스는 스스로를 게시할 수 있고 클라이언트는 게시된 서비스를 찾을 수 있습니다. 서비스가 검색 가능하게 되면 해당 서비스는 검색 요청을 수신하고 이에 대해 응답하는 것 외에 알림 메시지를 보낼 수도 있습니다. 검색 가능한 서비스는 Hello 메시지를 보내 네트워크에서 서비스의 도착을 알리며, Bye 메시지를 보내 네트워크에서 서비스의 출발을 알립니다. 클라이언트는 서비스를 찾기 위해 서비스 계약 형식, 키워드 및 네트워크 범위와 같은 특정 조건이 포함된 Probe 요청을 보냅니다. 서비스는 Probe 요청을 받고 자신이 이 조건에 일치하는지 여부를 확인합니다. 일치할 경우 서비스는 서비스에 연결하는 데 필요한 정보와 함께 ProbeMatch 메시지를 클라이언트로 돌려보내 응답합니다. 또한 클라이언트는 끝점 주소가 변경된 경우에도 서비스를 찾을 수 있는 Resolve 요청을 보낼 수도 있습니다. 일치하는 서비스는 ResolveMatch 메시지를 클라이언트로 돌려보내 Resolve 요청에 응답합니다.
애드혹 및 관리 모드
Discovery API가 지원하는 모드는 관리 모드와 애드혹 모드, 두 가지입니다. 관리 모드에는 사용 가능한 서비스에 대한 정보를 유지 관리하는 검색 프록시라는 중앙 서버가 있습니다. 검색 프록시는 다양한 방법을 통해 서비스에 대한 정보로 채워집니다. 예를 들어 서비스가 시작 시에 검색 프록시로 알림 메시지를 보낼 수도 있고, 프록시가 데이터베이스 또는 구성 파일에서 데이터를 읽어 사용 가능한 서비스를 확인할 수도 있습니다. 검색 프록시를 채우는 방법은 전적으로 개발자의 재량에 따라 결정됩니다. 클라이언트는 검색 프록시를 통해 사용 가능한 서비스에 대한 정보를 검색합니다. 클라이언트는 서비스를 검색할 때 검색 프록시로 Probe 메시지를 보내며, 프록시는 자신이 아는 서비스 중에 클라이언트가 검색하는 서비스와 일치하는 서비스가 있는지 여부를 확인합니다. 일치하는 서비스가 있으면 검색 프록시는 클라이언트로 ProbeMatch 응답을 돌려보냅니다. 그러면 클라이언트는 프록시에서 반환된 서비스 정보를 사용하여 서비스에 직접 연결합니다. 관리 모드의 기반이 되는 핵심 원칙은 검색 요청이 하나의 기관, 즉 검색 프록시로 유니캐스트 방식으로 전송된다는 것입니다. .NET Framework에는 사용자가 직접 프록시를 빌드할 수 있도록 하는 주요 구성 요소가 포함되어 있습니다. 클라이언트와 서비스는 다음과 같은 여러 방법으로 프록시를 찾을 수 있습니다.
프록시는 애드혹 메시지에 응답할 수 있습니다.
프록시는 시작 시 알림 메시지를 보낼 수 있습니다.
잘 알려진 특정 끝점을 찾도록 클라이언트 및 서비스를 작성할 수 있습니다.
애드혹 모드에는 중앙 서버가 없습니다. 서비스 알림 및 클라이언트 요청과 같은 모든 검색 메시지는 멀티캐스트 방식으로 전송됩니다. 기본적으로 .NET Framework에는 UDP 프로토콜을 통한 애드혹 검색 지원이 포함되어 있습니다. 예를 들어 서비스가 시작 시 Hello 알림을 보내도록 구성된 경우 이 서비스는 UDP 프로토콜을 사용하여 잘 알려진 멀티캐스트 주소를 통해 알림을 보냅니다. 클라이언트는 적극적으로 이러한 알림을 수신하고 적절히 처리해야 합니다. 클라이언트는 서비스에 대한 Probe 메시지를 보낼 때 멀티캐스트 프로토콜을 사용하여 네트워크를 통해 이 메시지를 보냅니다. 요청을 받는 각 서비스는 Probe 메시지에 포함된 조건과 자신이 일치하는지 여부를 확인하고, Probe 메시지에 지정된 조건과 일치하는 경우 ProbeMatch 메시지로 클라이언트에 직접 응답합니다.
WCF Discovery를 사용할 경우의 장점
WCF Discovery는 WS-Discovery 프로토콜을 사용하여 구현되므로 WS-Discovery를 구현하는 다른 클라이언트, 서비스 및 프록시와 상호 운용이 가능합니다. WCF Discovery는 기존 WCF API를 기반으로 구축되므로 기존 서비스 및 클라이언트에 검색 기능을 손쉽게 추가할 수 있습니다. 서비스 검색 기능은 응용 프로그램 구성 설정을 통해 쉽게 추가할 수 있습니다. 또한 WCF Discovery는 피어 넷, 명명 오버레이 및 HTTP와 같은 다른 전송에서의 검색 프로토콜 사용도 지원합니다. WCF Discovery는 검색 프록시가 사용되는 작업의 관리 모드를 지원합니다. 이로써 전체 네트워크로 멀티캐스트 메시지를 보내는 대신 검색 프록시로 메시지를 직접 보내게 되므로 네트워크 트래픽이 감소합니다. WCF Discovery는 웹 서비스와 함께 사용할 때 유연성도 더욱 높여 줍니다. 예를 들어 클라이언트나 서비스를 다시 구성할 필요 없이 서비스 주소를 변경할 수 있습니다. 클라이언트는 서비스에 액세스해야 하는 경우 Find 요청을 통해 Probe 메시지를 발송하고 서비스가 현재 주소를 사용하여 응답하기를 기다립니다. WCF Discovery를 통해 클라이언트는 계약 형식, 바인딩 요소, 네임스페이스, 범위 및 키워드 또는 버전 번호와 같은 다양한 조건에 따라 서비스를 검색할 수 있습니다. WCF Discovery를 사용하면 런타임 및 디자인 타임 검색이 가능합니다. 내결함성 및 자동 구성과 같은 다른 시나리오를 지원하기 위해 응용 프로그램에 검색 기능을 추가할 수 있습니다.
서비스 게시
서비스 검색을 가능하게 하려면 서비스 호스트에 ServiceDiscoveryBehavior를 추가하고 검색 끝점을 추가하여 검색 메시지를 수신할 위치를 지정해야 합니다. 다음 코드 예제에서는 자체 호스팅 서비스를 검색 가능하도록 수정하는 방법을 보여 줍니다.
Uri baseAddress = new Uri(string.Format("http://{0}:8000/discovery/scenarios/calculatorservice/{1}/",
System.Net.Dns.GetHostName(), Guid.NewGuid().ToString()));
// Create a ServiceHost for the CalculatorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
{
// add calculator endpoint
serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), string.Empty);
// ** DISCOVERY ** //
// make the service discoverable by adding the discovery behavior
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// ** DISCOVERY ** //
// add the discovery endpoint that specifies where to publish the services
serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
}
서비스를 검색 가능하게 하려면 서비스 설명에 ServiceDiscoveryBehavior 인스턴스를 추가해야 합니다. 서비스에 검색 요청을 수신할 위치를 알리려면 서비스 호스트에 DiscoveryEndpoint 인스턴스를 추가해야 합니다. 이 예제에서는 UdpDiscoveryEndpoint(DiscoveryEndpoint에서 파생됨)를 추가하여 서비스가 UDP 멀티캐스트 전송을 통해 검색 요청을 수신하도록 지정합니다. 모든 메시지가 멀티캐스트 방식으로 전송되므로 애드혹 검색을 위해 UdpDiscoveryEndpoint가 사용됩니다.
알림
기본적으로 서비스 게시는 알림 메시지를 보내지 않습니다. 알림 메시지를 보내도록 서비스를 구성해야 합니다. 이렇게 하면 서비스 작성기가 검색 메시지 수신과는 별도로 서비스를 알릴 수 있으므로 유연성이 높아집니다. 서비스 알림은 검색 프록시 및 기타 서비스 레지스트리에 서비스를 등록하기 위한 메커니즘으로도 사용할 수 있습니다. 다음 코드는 UDP 바인딩을 통해 알림 메시지를 보내도록 서비스를 구성하는 방법을 보여 줍니다.
Uri baseAddress = new Uri(string.Format("http://{0}:8000/discovery/scenarios/calculatorservice/{1}/",
System.Net.Dns.GetHostName(), Guid.NewGuid().ToString()));
// Create a ServiceHost for the CalculatorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
{
// add calculator endpoint
serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), string.Empty);
// ** DISCOVERY ** //
// make the service discoverable by adding the discovery behavior
ServiceDiscoveryBehavior discoveryBehavior = new ServiceDiscoveryBehavior();
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// send announcements on UDP multicast transport
discoveryBehavior.AnnouncementEndpoints.Add(
new UdpAnnouncementEndpoint());
// ** DISCOVERY ** //
// add the discovery endpoint that specifies where to publish the services
serviceHost.Description.Endpoints.Add(new UdpDiscoveryEndpoint());
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
}
서비스 검색
클라이언트 응용 프로그램은 DiscoveryClient 클래스를 사용하여 서비스를 찾을 수 있습니다. 개발자는 Probe 또는 Resolve 메시지를 보낼 위치를 지정하는 검색 끝점을 전달하는 DiscoveryClient 클래스의 인스턴스를 만듭니다. 그러면 클라이언트가 FindCriteria 인스턴스 내에서 검색 조건을 지정하는 Find를 호출합니다. 일치하는 서비스가 발견되면 Find는 EndpointDiscoveryMetadata 컬렉션을 반환합니다. 다음 코드는 Find 메서드를 호출한 다음 검색된 서비스에 연결하는 방법을 보여 줍니다.
class Client
{
static EndpointAddress serviceAddress;
static void Main()
{
if (FindService()) InvokeService();
}
// ** DISCOVERY ** //
static bool FindService()
{
Console.WriteLine("\nFinding Calculator Service ..");
DiscoveryClient discoveryClient =
new DiscoveryClient(new UdpDiscoveryEndpoint());
Collection<EndpointDiscoveryMetadata> calculatorServices =
discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
discoveryClient.Close();
if (calculatorServices.Count == 0)
{
Console.WriteLine("\nNo services are found.");
return false;
}
else
{
serviceAddress = calculatorServices[0].EndpointAddress;
return true;
}
}
static void InvokeService()
{
Console.WriteLine("\nInvoking Calculator Service at {0}\n", serviceAddress);
// Create a client
CalculatorClient client = new CalculatorClient();
client.Endpoint.Address = serviceAddress;
client.Add(10,3);
}
검색 및 메시지 수준 보안
메시지 수준 보안을 사용하는 경우 서비스 검색 끝점에 EndpointIdentity를, 클라이언트 검색 끝점에 일치하는 EndpointIdentity를 지정해야 합니다. 메시지 수준 보안에 대한 자세한 내용은 WCF의 메시지 보안을 참조하십시오.