次の方法で共有


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 を呼び出します。一致するサービスが見つかった場合、FindEndpointDiscoveryMetadata のコレクションを返します。次のコードは、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 のメッセージのセキュリティ」を参照してください。