WCF Discovery の概要
Discovery API は、WS-Discovery プロトコルを使用した Web サービスの動的公開と探索の統合プログラミング モデルを提供します。これらの API は、サービスがサービス自体を公開し、クライアントが公開されたサービスを発見できるようにします。サービスを探索可能にした後は、サービスでアナウンス メッセージを送信できるほか、探索要求のリッスンと応答もできるようになります。探索可能なサービスは、ネットワークに接続されたことをアナウンスする Hello メッセージ、およびネットワークから切断されたことをアナウンスする Bye メッセージを送信できます。サービスを検索するために、クライアントは、サービス コントラクト型、キーワード、ネットワークのスコープなど、特定の条件が設定された Probe 要求を送信します。サービスはこの Probe 要求を受信し、条件に一致するかどうかを判断します。サービスが条件に一致した場合は、サービスへの接続に必要な情報と併せて ProbeMatch メッセージをクライアントに送り返すことで応答します。クライアントは Resolve 要求を送信することもできます。この要求では、エンドポイント アドレスが変更されている可能性があるサービスを発見できます。条件に一致したサービスは、ResolveMatch メッセージをクライアントに送り返すことで、Resolve 要求に応答します。
アドホック モードとマネージ モード
Discovery API は、マネージとアドホックという 2 種類のモードをサポートします。マネージ モードでは、使用可能なサービスについての情報を管理する探索プロキシと呼ばれる集中サーバーがあります。探索プロキシには、さまざまな方法でサービスについての情報を設定できます。たとえば、サービスから起動中にアナウンス メッセージを探索プロキシに送信することも、探索プロキシがデータベースや構成ファイルからデータを読み取って、使用可能なサービスを特定することもできます。探索プロキシへの情報の設定方法は、開発者が決定します。クライアントは、探索プロキシを使用して、使用可能なサービスについての情報を取得します。クライアントは、サービスを検索するときに Probe メッセージを探索プロキシに送信します。探索プロキシは、認識しているサービスのうち、クライアントが検索しているサービスに一致するものがあるかどうかを判断します。一致するものがあった場合、探索プロキシは ProbeMatch 応答をクライアントに返します。クライアントは、プロキシから返されたサービスの情報を使用して、直接サービスにアクセスします。マネージ モードの基盤である最大の原則は、探索要求がユニキャストで 1 つの機構、つまり、探索プロキシに送信されることです。.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 では、Web サービスをより柔軟に操作することもできます。たとえば、クライアントやサービスを再構成することなく、サービスのアドレスを変更できます。クライアントがサービスにアクセスする必要がある場合、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 のメッセージのセキュリティ」を参照してください。