Microsoft .NET Remoting Framework の概要

Paddy Srinivasan
Microsoft Corporation

要約: この記事では、Microsoft .NET Remoting Framework の基本について説明します。.NET Remoting Framework を形成する主要コンポーネントの説明に加えて、.NET Remoting を使用して分散オブジェクトと通信するためのさまざまなシナリオについても述べます。

注 : この記事では、Beta 2 用にソースコードを更新しています。

  • はじめに
  • .NET Remoting オブジェクト
  • .NET Remoting オブジェクトのホスティング
  • .NET Remoting のメタデータ ファイルと構成ファイル
  • .NET Remoting シナリオ
  • まとめ
  • 関連資料

はじめに

Microsoft® .NET Remoting は、さまざまな AppDomain やプロセス、そしてさまざまなマシンに存在するオブジェクトが、互いにシームレスに通信するための高性能かつ拡張性の高い枠組みを提供します。.NET Remoting は、これらの対話を透過的にするための非常にパワフルでありながらシンプルなプログラミング モデルとランタイム サポートを提供します。この記事では、Remoting アーキテクチャの種々の基本構成要素を概説し、.NET Remoting を利用できる一般的なシナリオのいくつかを紹介します。.NET Remoting オブジェクトは、SOAP コールを発行できる任意のクライアントから .NET Remoting オブジェクトへのアクセスを可能とする Web サービスとして公開できます (MSDN Magazine の記事「プログラマブル Web: Microsoft .NET Framework のビルディング ブロックを提供する Web Services」を参照してください)。.NET Remoting の概要については、始めに「Microsoft .NET リモーティング: 技術概要」をお読みください。

.NET Remoting オブジェクト

.NET リモート オブジェクトとして機能するように構成できるオブジェクトには、次の 3 つの種類があります。アプリケーションの要件に応じて、オブジェクトの種類を選ぶことができます。このセクションでは、次のオブジェクトについて詳しく説明します。

  • シングル コール
    シングル コール オブジェクトは、状態の格納することを要求されまません。そして、複数のメソッド コールにわたって状態を保持することはできません。しかしながら、シングル コール オブジェクトは、ロードバランス構成に利用できます。

  • シングルトン オブジェクト
    シングルトン オブジェクトは、複数のクライアントにサービスを提供するオブジェクトであり、複数のクライアント呼び出しにわたって状態に関する情報を格納することによってデータを共有します。シングルトン オブジェクトは、クライアント間でデータを明示的に共有する必要がある場合や、オブジェクトの作成と保持にかなりのオーバーヘッドが伴う場合に役立ちます。

  • クライアント起動オブジェクト (Client Activated Objects : CAO)
    クライアント起動オブジェクト (Client Activated Objects : CAO) は、クライアントからの要求に応じて起動されるサーバー側オブジェクトです。このようなサーバー オブジェクトの起動は、既存の COM coclass の起動によく似ています。クライアントが "new" 演算子を使用してサーバー オブジェクトを要求すると、起動要求メッセージがリモート アプリケーションに送信されます。サーバーは要求されたクラスのインスタンスを作成して、呼び出し側クライアント アプリケーションに ObjRef を返します。ObjRef を使用して、クライアント側にプロキシが作成されます。クライアントのメソッド コールは、このプロキシ上で実行されます。クライアント起動オブジェクトは、特定のクライアントを対象とするメソッド コール間では状態を格納できますが、異なるクライアント オブジェクト間では状態を格納できません。"new" の呼び出しのたびに、そのサーバー タイプの独立したインスタンスへのプロキシが返されます。

    .NET Remoting を使用したオブジェクトの受け渡し

    .NET Remoting では、次のようにして、アプリケーションから別のアプリケーションへオブジェクトを渡すことができます。

    1. メソッド コールのパラメータとして
      例: public int myRemoteMethod (MyRemoteObject myObj)
    2. メソッド コールの戻り値
      例: public MyRemoteObject myRemoteMethod(String myString)
    3. .NET コンポーネントのプロパティまたはフィールド アクセスの結果としての値
      例: myObj.myNestedObject

    "値によるマーシャリング (Marshal By Value: MBV)" に対応するオブジェクトについては、アプリケーションから別のアプリケーションにオブジェクトが渡されるときに、オブジェクトの完全なコピーが作成されます。

    "参照によるマーシャリング (Marshal By Reference: MBR)" に対応するオブジェクトについては、アプリケーションから別のアプリケーションにオブジェクトが渡されるときに、オブジェクトの参照が作成されます。オブジェクト参照 (ObjRef) はリモート アプリケーションに着信すると、プロキシ経由で元のオブジェクトに返されます。

    単純な .NET Remoting サーバー オブジェクトのサンプル コード

    using System;
    using System.Runtime.Remoting;
    namespace myRemoteService
    {
        // 既知の Web サービス オブジェクト
        public class myRemoteObject : MarshalByRefObject
        {
            // メソッド myRemoteMethod
            public String myRemoteMethod(String s) 
            {
            return "Hello World";
            }
        }
    }
    

    このオブジェクトにアクセスするサンプル クライアント コード

    using System;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Http;
    using myRemoteService;
    public class Client
    {
        public static int Main(string[] args)
        {
            ChannelServices.RegisterChannel(new HttpChannel());
          // myRemoteObject クラスのインスタンスを作成する
      myRemoteObject myObj = ( myRemoteObject)Activator.GetObject(typeof(myRemoteObject),
                "http://myHost:7021/host/myRemoteObject.soap");
          myObj. myRemoteMethod ("Hello World");
            return 0;
        }
    }
    

    リース 形成のライフタイム

    オブジェクトの参照がアプリケーションの外部に送信される場合は、リース期間が作成されます。リースには、リース期間があります。リース期間がゼロになると、リースの有効期限が切れて、オブジェクトは .NET Remoting フレームワーク から切断されます。AppDomain 内のオブジェクトの参照がすべて解放されると、次の ガーベッジ コレクション が発生したときにオブジェクトが収集されます。リースは、オブジェクトのライフタイムを制御します。

    オブジェクトにはデフォルトのリース期間がありますが、クライアントが同じサーバー オブジェクトの状態を保持したい場合に備えて、リース期間を延長してオブジェクトをアクティブにしておく、いくつかの方法があります。

    1. サーバー オブジェクトは、リース期間を無限に設定することができます。この場合、Remoting はガベージ コレクション サイクルでオブジェクトの収集を行わなくなります。

    2. クライアントは、RemotingServices.GetLifetimeService メソッドを呼び出して、AppDomain のリース マネージャからサーバー オブジェクトのリースを取得することができます。Lease オブジェクトから、クライアントは Lease.Renew メソッドを呼び出して、リースを延長することができます。

    3. クライアントは、特定のリースのスポンサーを AppDomain のリース マネージャに登録することができます。リモート オブジェクトのリース期限が切れると、リース マネージャはスポンサーにリースの更新を要求します。

    4. ILease::RenewOnCallTime プロパティが設定されている場合は、リモート オブジェクトへのコールのたびに、RenewOnCallTime プロパティで設定された時間だけ、リースが更新されます。

      シングル コール/シングルトン オブジェクト クライアント起動オブジェクト

    クライアント側起動コード (クライアント側に必要なコード)

    詳細については、構成ファイルのセクションを参照してください。

    a) Activator.GetObject()
    b) new() と CFG ファイル

    クライアントの CFG ファイルは、次の URL を参照します。

    Foo= https://localhost:80/ObjectZone/Foo.soap

    a) Activator.CreateInstance()
    b) new() と CFG ファイル

    クライアントの CFG ファイルは、次の URL を参照します。

    https://localhost:80/ObjectZone

    サーバー オブジェクトの起動 最初のメソッド コールが行われるまで、起動メッセージはネットワークへ送信されません。 起動メッセージは、クライアントがオブジェクトを作成して、クライアント側にプロキシが作成されたときに、サーバー マシンに送信されます。パラメータ付きコンストラクタがサポートされます。
    サーバー オブジェクトのライフタイム ライフタイムは、サーバー上の構成によって決まります。SingleCall または Singleton のいずれかです。シングルトン オブジェクトもまた、ライフタイム管理を必要とします。

    ライフタイムは、次の 2 つのイベントのいずれか早い方が適用されます。
    a) リース期限が切れたとき。
    b) クライアントがサーバー オブジェクトの参照を失ったとき。

    サーバー側の登録

    a) 構成ファイルを使用して、種類 (SingleCall または Singleton) を指定します。
    b) RegisterWellKnownType() API を使用して、種類を指定します。

    構成ファイルを使用して、クライアント起動オブジェクトをエクスポートします。
    詳細については、構成ファイルのセクションを参照してください。

    モデルの利点

    a) サーバー コンポーネントの基底クラスまたはインターフェイス定義の Common Language Runtime メタデータに対して、クライアントをコンパイルすることができます。
    b) サーバー側で少量の操作を実行するのに便利です。
    c) シングル コール オブジェクトは状態を保持しないので、負荷分散を実装したシステムへの導入が容易です。
    d) シングルトン オブジェクトは、複数のクライアント オブジェクトにまたがって状態を保持することができます。

    a) サーバー オブジェクトの呼び出しは、既存の COM の「coclass」に似ています。
    b) クライアントは、サーバー オブジェクトのライフタイムをより柔軟に制御できます。
    c) クライアントは、作成されたオブジェクトにコンストラクタ パラメータを渡すことができます。
    d) サーバー オブジェクトは、複数のメソッド コールにわたって特定のクライアントの状態を保持することができます。

.NET Remoting オブジェクトのホスティング

.NET Remoting オブジェクトは、次のようにホストできます。

  1. マネージ実行可能ファイル。 .NET Remoting オブジェクトは、通常の .NET コンポーネントまたはサービスコンポーネントでホストすることができます。

  2. IIS。 Remoting オブジェクトは、Internet Information Server (IIS) でホストすることができます。デフォルトでは、IIS でホストされる Remoting オブジェクトは、HTTP チャンネルを通じてメッセージを受信します。IIS で Remoting オブジェクトをホストするには、仮想ルートを作成して、そこに "remoting.cfg" ファイルをコピーする必要があります。リモート オブジェクトを含んでいる実行可能ファイルまたは DLL は、IIS ルートが指すディレクトリ直下の bin ディレクトリに置く必要があります。IIS ルート名は、構成ファイルで指定されているアプリケーション名と同じでなければならないので注意してください。Remoting 構成ファイルは、最初のメッセージがアプリケーションに着信したときに自動的にロードされます。このようにして、.NET Remoting オブジェクトを Web サービスとして公開することができます。

    サンプル Remoting.cfg ファイル(file:)

    <configuration>
    <system.runtime.remoting>
      <application name="RemotingHello">
    
        <service>
          <wellknown mode="SingleCall" 
                    type="Hello.HelloService, Hello" 
                    objectUri="HelloService.soap" />
        </service>
    
        <channels>
          <channel port="8000" 
            type="System.Runtime.Remoting.Channels.Http.HttpChannel, 
            System.Runtime.Remoting" />
        </channels>
    
      </application>
    </system.runtime.remoting>
    </configuration>
    
  3. .NET コンポーネント サービス。 .NET Remoting オブジェクトを .NET コンポーネント サービス インフラストラクチャでホストすることによって、トランザクション、JIT、オブジェクト プーリングなど、さまざまな COM+ サービスを利用することができます。

    詳細については、「Microsoft .NET Framework のコンポーネント サービス、第 1 部」を参照してください。

チャンネル サービス (System.Runtime.Remoting.Channels)

.NET アプリケーションと AppDomain は、メッセージを使用して互いに通信します。.NET チャンネル サービス は、この通信の基盤となるトランスポート メカニズムを提供します。

.NET Framework は HTTP、TCP、および SMTP チャンネルを提供しますが、サードパーティが独自のチャンネルを作成して、プラグインすることもできます。HTTP チャンネルおよび SMTP チャンネルはデフォルトでは SOAP を使用して通信しますが、TCP チャンネルはデフォルトではバイナリ 形式を使用します。

チャンネル サービスは、カスタム チャンネル (IChannel) を使用したプラグインが可能であり、異種アプリケーションの統合が可能です。

チャンネル サービスをロードするサンプル コード


  public class myRemotingObj
{
    HttpChannel httpChannel;
    TcpChannel tcpChannel;
    public void myRemotingMethod()
    {
        httpChannel =  new HttpChannel();
        tcpChannel  =  new TcpChannel();
        ChannelServices.RegisterChannel(httpChannel);
        // HTTP チャンネルを登録する
        ChannelServices.RegisterChannel(tcpChannel);
        // TCP チャンネルを登録する 
    }
} 

シリアライゼーション フォーマッタ (System.Runtime.Serialization.Formatters)

.NET シリアライゼーション フォーマッタは、.NET アプリケーションと AppDomain の間でメッセージのエンコードとデコードを行います。.NET ランタイムには、Binary (System.Runtime.Serialization.Formatters.Binary) と SOAP (System.Runtime.Serialization.Formatters.Soap) の 2 つのネイティブ フォーマッタがあります。

シリアライゼーション フォーマッタは、IRemotingFormatter インターフェイスをインプリメントして、それを前述のチャンネルにプラグインすることによって使用可能となります。このプロセスは、この記事で後述しますが、アプリケーションに最適なチャンネルとフォーマッタの組み合わせを柔軟に選ぶことができます。

例 : HTTP チャンネルで、バイナリ データをシリアライズする Binary フォーマッタを使用し、TCP チャンネルで SOAP フォーマッタを使用することもできます。

Remoting コンテキスト

コンテキスト とは、共通のランタイム プロパティを共有するオブジェクトを収めた境界です。コンテキスト属性の例としては、同期とスレッド 親和性があります。.NET オブジェクトが起動すると、ランタイムが現在のコンテキストの互換性をチェックして、互換性がない場合には新しいコンテキストが作成されます。コンテキストの中では、複数のオブジェクトを同時に実行することができ、AppDomain は複数のコンテキストを持つことができます。

あるコンテキスト内のオブジェクトから別のコンテキスト内のオブジェクトへのコールは、コンテキスト プロキシを通じて行われ、コンテキスト プロパティの組み合わせによるポリシーの影響を受けます。新しいオブジェクトのコンテキストは、一般に、クラスのメタデータ属性に基づいて選択されます。

コンテキストに結び付けることができるクラスを、コンテキスト バインド クラスといいます。コンテキスト バインド クラスの属性は、コンテキスト属性と呼ばれる特殊なカスタム属性によって指定することができます。コンテキスト属性は完全に拡張可能であり、これらの属性を作成して、クラスにアタッチすることができます。コンテキストにバインドされるオブジェクトは、System.ContextBoundObject から派生したものです。

.NET Remoting のメタデータ ファイルと構成ファイル

.NET Framework は、メタデータとアセンブリを使用して、コンポーネントに関する情報を格納し、クロス言語プログラミングを可能にします。.NET Remoting は、メタデータを使用して、プロキシ オブジェクトを動的に作成します。クライアント側で作成されるプロキシ オブジェクトは、オリジナルのクラスと同じメンバを持ちます。しかし、プロキシ オブジェクトの実装は、すべての要求を .NET Remoting ランタイムを通じてオリジナルのオブジェクトに転送します。シリアライゼーション フォーマッタは、メタデータを使用して、メソッド コールとペイロード ストリームとの間の変換を行います。

クライアントは、リモート オブジェクトへのアクセスに必要なメタデータを次のような方法で取得することができます。

  1. サーバー オブジェクトの .NET アセンブリ — サーバー オブジェクトはメタデータ アセンブリを作成して、それをクライアントに配布することができます。クライアント オブジェクトは、クライアント オブジェクトのコンパイル時にアセンブリを参照することができます。これは、クライアントとサーバーがマネージコンポーネントである、特定の状況で非常に有効です。

  2. Remoting オブジェクトは、オブジェクトとメソッドを記述する WSDL (「Web サービス記述言語 (WSDL) 1.0」を参照) ファイルを提供することができます。WSDL ファイルに対応する SOAP 要求の読み取りと生成ができるクライアントは、このオブジェクトを呼び出して、SOAP を使用して通信することができます。.NET Remoting サーバー オブジェクトは、.NET SDK に含まれている SOAPSUDS.EXE ツールを使用して、メタデータとして機能する WSDL ファイルを生成することができます。これは、どんなクライアントからでもアクセスと使用が可能なパブリックなサービスを提供したい場合に役立ちます。

  3. .NET クライアントは、SOAPSUDS ユーティリティを使用してサーバーから (サーバー上で生成された) XML スキーマをダウンロードして、メタデータだけを含み、コードを含まないソース ファイルまたはアセンブリを生成することができます。ソース ファイルは、オプションでクライアント アプリケーションにコンパイルすることができます。この方法は、ある層のオブジェクトから別の層のリモート オブジェクトにアクセスする必要がある多階層アプリケーションで役立ちます。

構成ファイル (.CFG ファイル) を使用して、特定のオブジェクトについての Remoting 固有の各種の情報を指定することができます。通常、それぞれの AppDomain に専用の CFG ファイルがあります。CFG ファイルの使用は、位置透過性の実現に役立ちます。CFG ファイルでの詳細の指定は、プログラム的に行うこともできます。CFG ファイルを使用した場合の主な利点は、クライアント コードから透過的な構成情報が分離されるので、ソース ファイルを編集して再コンパイルしなくても、CFG ファイルを変更するだけで、将来の変更が可能になることです。構成ファイルは、.NET Remoting のクライアント オブジェクトとサーバー オブジェクトの両方で使用されます。

典型的な CFG ファイルは、特に次のような情報を含みます。

  1. ホスト アプリケーション情報

  2. オブジェクトの名前

  3. オブジェクトの URI

  4. 登録されているチャンネル (同時に複数のチャンネルを登録することができます)

  5. サーバー オブジェクトのリース期間

サンプル構成ファイル (この書式は、将来のリリースで XML に変更される可能性があります):


  <configuration>
  <system.runtime.remoting>
    <application name="HelloNew">

      <lifetime leaseTime="20ms" sponsorshipTimeout="20ms" 
      renewOnCallTime="20ms" />  

      <client url="https://localhost:8000/RemotingHello">
        <wellknown type="Hello.HelloService, MyHello" 
      url="https://localhost:8000/RemotingHello/HelloService.soap" />
        <activated type="Hello.AddService, MyHello"/>
      </client>
      
      <channels>
        <channel port="8001" 
        type="System.Runtime.Remoting.Channels.Http.HttpChannel, 
        System.Runtime.Remoting" />
      </channels>
      
    </application>
  </system.runtime.remoting>
</configuration>

.NET Remoting シナリオ

.NET Remoting の動作を理解したところで、今度は .NET Remoting を活用できるさまざまなシナリオを見てみましょう。次の表は、クライアントとサーバーの組み合わせと、デフォルトで使用される基盤プロトコルとペイロードの一覧です。.NET Remoting Framework は拡張可能であり、ユーザー独自の通信チャンネルとシリアライゼーション フォーマッタの作成が可能であることを念頭においてください。

クライアント サーバー ペイロード プロトコル
.NET コンポーネント .NET コンポーネント SOAP/XML http
.NET コンポーネント .NET コンポーネント バイナリ TCP
マネージ/非マネージ .NET Web サービス SOAP/XML http
.NET コンポーネント 非マネージクラシック COM コンポーネント NDR (Network Data Representation) DCOM
非マネージクラシック COM コンポーネント .NET コンポーネント NDR DCOM

HTTP-SOAP を使用する任意のクライアント <-> .NET

Web サービスは、クライアントにプログラム的に情報を返す URL アドレス指定可能なリソースです。クライアントは、実装の詳細を気にせずに Web サービスを使用することができます。Web サービスは、Web Services Description Language (WSDL) ファイルを使用して記述される、コントラクトと呼ばれる明確に定義されたインターフェイスを使用します。WSDL の詳細については、「Web サービス記述言語 (WSDL) 1.0」を参照してください。

.NET Remoting オブジェクトは、IIS でホストすることによって、Web サービスとして公開することができます。WSDL ファイルを利用するクライアントは、WSDL ファイルで指定されたコントラクトに従って、リモート オブジェクトへの SOAP コールを行うことができます。IIS は、ISAPI 拡張を使用して、適切なオブジェクトに要求を送ります。このように、Remoting オブジェクトは Web サービス オブジェクトとして機能することができ、高機能な .NET フレームワーク インフラストラクチャを利用することができます。この構成は、さまざまなプラットフォームや環境のプログラムからオブジェクトへのアクセスを可能にしたい場合に役立ちます。Web サービスの詳細については、「プログラマブル Web: Microsoft .NET Framework のビルディング ブロックを提供する Web Services」を参照してください。この構成は、クライアントからファイヤウォール経由での .NET オブジェクトへのアクセスを容易にします。

HTTP-SOAP を通じて Remoting オブジェクトの Web サービスを呼び出すクライアントの例

図 1. HTTP-SOAP を通じて Remoting オブジェクトの Web サービスを呼び出すクライアントの例

SOAP-HTTP チャンネルを使用する .NET<->.NET

HTTP チャンネルは、デフォルトでは SOAP フォーマッタを使用するので、クライアントがインターネット経由でオブジェクトにアクセスする状況で利用できます。このアプローチは HTTP を使用するので、ファイヤウォール経由で .NET オブジェクトへのアクセスが、この構成によって可能になります。このようにして公開されたオブジェクトは、前のセクションで説明したように、IIS でホストするだけで容易に Web サービス オブジェクトとして構成することができます。クライアントは、これらのオブジェクトの WSDL ファイルを読み取って、SOAP を使用してリモート オブジェクトと通信できます。

TCP チャンネルを使用する .NET<->.NET

TCP チャンネルは、デフォルトではバイナリ フォーマッタを使用します。このフォーマッタは、データをバイナリ形式でシリアライズし、ソケットを使用してデータをネットワーク転送します。ファイヤウォールの境界で閉じられた環境にオブジェクトが配置される場合には、この方法が理想的です。このアプローチは、オブジェクト間でバイナリ データを伝達するためにソケットを使用するので、高度に最適化されています。TCP チャンネルを使用してオブジェクトを公開することによって、閉じられた環境でのオーバーヘッドの低さを活かすことができます。このアプローチは、ファイヤウォールと構成上の問題のため、インターネット経由では使用できません。

TCP チャンネルを使用して、マシンの境界にまたがって Remoting オブジェクトを呼び出すクライアントの例

図 2. TCP チャンネルを使用して、マシンの境界にまたがって Remoting オブジェクトを呼び出すクライアントの例

.NET <-> アンマネージ COM コンポーネント <-> .NET

COM Interop サービス を通じて、アンマネージの COM コンポーネントを呼び出すことが可能です。.NET Remoting クライアント オブジェクトが COM オブジェクトのインスタンスを作成すると、オブジェクトは、実際のアンマネージオブジェクトのプロキシの役目を果たすランタイム コーラブル ラッパー (RCW) を通じて公開されます。これらのラッパーは、.NET クライアントからはほかのマネージクラスと同じように見えますが、実際には、マネージ (.NET) コードとアンマネージ (COM) コードの間でコールをマーシャリングするだけです。

同様に、.NET Remoting サーバー オブジェクトを COM クライアントに対して公開することができます。COM クライアントが .NET オブジェクトのインスタンスを作成すると、オブジェクトは、実際のマネージオブジェクトのプロキシの役目を果たす COM コーラブル ラッパー (CCW) を通じて公開されます。

これらのシナリオでは、どちらも通信に DCOM を使用します。この相互運用性は、COM と .NET コンポーネントの混在状況で非常に有効です。このトピックの詳細については、「COM Interoperability Specification」(英語)を参照してください。

まとめ

Microsoft .NET Framework は、堅牢でスケーラブルな分散システムを開発するための、パワフルで拡張可能な、そして言語に依存しない枠組みを提供します。.NET Remoting フレームワークは、システムの要件に応じたリモート対話のためのパワフルな手段を提供します。.NET Remoting は Web サービスとシームレスに連携して、複数のプラットフォームにまたがるアクセスのために、.NET オブジェクトを公開する手段を提供します。

関連資料

.NET Remoting の詳細については、以下の資料を参照してください。

Microsoft .NET の最新情報については、弊社 Web サイト https://www.microsoft.com/japan/developer/net/ をご覧ください。