はじめに
追跡サービス(Tracking Service)とは、その名前から想像されるように、オブジェクトのライフサイクルに関係するさまざまな活動を追跡するものです。このサービスは.NET Remotingフレームワークの一部なので、.NET Remotingの概念を復習しておきましょう。
.NET Remoting
Microsoftの.NETフレームワークは、アプリケーションドメイン内のクライアントから別のアプリケーションドメイン内のオブジェクトにアクセスする仕組みを提供しています。これを可能にするのが.NET Remotingです。
.NET Remotingは非常に柔軟性の高いテクノロジであり、クライアントとサーバーがどこにあっても相互に通信できるようにします。クライアントとサーバーの場所は、同じコンピュータ上でも、同じネットワーク上の別のコンピュータでも、海を隔てた別の国のコンピュータでもかまいません。.NET Remotingのサービスやインフラストラクチャコンポーネントを利用することにより、アプリケーション開発者は複雑な要素を意識せずに済みます。
.NET Remotingでは各種のプロトコルやシリアル化形式、設定情報を使用できます。また.NET Remotingパイプライン内に独自の「フック」を設ければ、リモートフレームワークの既定の動作をカスタマイズすることもできます(追跡サービスは、こうしたフックの一例です)。
では.NET Remotingの仕組みはどうなっているのでしょうか。.NET Remotingの概念の一部は、従来の分散テクノロジ(DCOM、CORBAなど)から借りてきたものです。まず明確にしておきたいのは、.NET Remotingでは、オブジェクトは何らかの「リスナプロセス」を通じて外部に公開されるという点です。このリスナプロセスはコンソールアプリケーションかもしれませんし、WinFormアプリケーションやWindowsサービス、あるいはIISということもあります。リスナプロセスは、プログラムまたは設定ファイルを通じて公開されるオブジェクトを指定します。オブジェクトが公開されている場合、クライアントアプリケーションはリスナプロセスに接続してオブジェクトの生成を要求し、リスナプロセスは生成したオブジェクトをクライアントに返します。クライアントとサーバーのアプリケーションドメイン間の通信は、エンコードされたデータストリームをチャネル上で送受信することによって行われます。
チャネル
チャネルの基本的な目的は、データをある場所から別の場所へ転送することです。.NETには既定で2つのチャネルが用意されています。1つはHTTPチャネル(System.Runtime.Remoting.Channels.Http)で、もう1つはTCPチャネル(System.Runtime.Remoting.Channels.Tcp)です。
TCPチャネルはHTTPチャネルよりも高速で、バイナリデータの転送に向いています。一方、HTTPチャネルはファイアウォールやインターネットを経由するときに適しています。使用できるのは、これらのチャネルに限りません。独自のチャネルを作成して.NET Remotingに組み込むこともできます。
フォーマッタ
フォーマッタとは、データやメッセージの体裁を送信用に整えるものです。フォーマットされたデータ/メッセージは、所定のチャネルを用いて他のアプリケーションドメインに転送されます。.NETには既定で2つのフォーマッタが用意されています。1つはSoapフォーマッタ(System.Runtime.Serialization.Formatters.Soap)で、もう1つはBinaryフォーマッタ(System.Runtime.Serialization.Formatters.Binary)です。
SoapフォーマッタはメッセージをSoap 1.1仕様に基づいてフォーマットし、Binaryフォーマッタはメッセージを純粋なバイナリ形式でフォーマットします。
リモート処理オブジェクトの種類
.NET Remotingは2種類のオブジェクトをサポートしています。1つはサーバーアクティブ化オブジェクト(「既知のオブジェクト」とも呼ばれます)で、もう1つはクライアントアクティブ化オブジェクトです。
サーバーアクティブ化オブジェクト
サーバーアクティブ化オブジェクトは、その名が示すとおり、サーバーによって生成され、その有効期間もサーバーによって管理されます。ここでポイントとなるのは、クライアントがNew
またはActivator.GetObject
を呼び出した時点では、これらのオブジェクトは生成されないことです。オブジェクトの実際のインスタンスが生成されるのは、クライアントがプロキシ上の特定のメソッドを実際に起動したときです。
この動作から1つ導かれることがあります。クライアントがNew
またはActivator.GetObject
メソッドを呼び出した時点でオブジェクトは生成されないので、サーバーアクティブ化オブジェクトでは、既定以外のコンストラクタは使えません。これらのオブジェクトでは、既定のコンストラクタ(パラメータを持たないコンストラクタ)だけがサポートされます。
サーバーアクティブ化オブジェクトは、2つのモードでアクティブにできます。
- Singleton ―― サーバー上にただ1つのオブジェクトが生成され、それがすべてのクライアントの要求を満たします。つまり、オブジェクトは共有され、オブジェクトの状態をすべてのクライアントが共有することになります。
- SingleCall ―― メソッド呼び出しごとにオブジェクトが生成され、オブジェクトがクライアント間で共有されることはありません。メソッド呼び出しが終了するたびにオブジェクトが破棄されるので、オブジェクトの状態は維持されません。
クライアントアクティブ化オブジェクト
クライアントアクティブ化オブジェクトは、サーバーによって生成され、その有効期間はクライアントによって管理されます。サーバーアクティブ化オブジェクトとは対照的に、クライアントアクティブ化オブジェクトは、クライアントがNew
またはその他のオブジェクト生成メソッドを呼び出したとき、直ちに生成されます。そのため、クライアントアクティブ化オブジェクトでは、既定のコンストラクタと既定以外のコンストラクタを共に使うことができます。クライアントアクティブ化オブジェクトは特定クライアントに限定され、クライアント間で共有されることはありません。オブジェクトのインスタンスはリース期限が切れるか、クライアントがオブジェクトを破棄するまで存続します。
設定
他の.NETテクノロジと同様、.NET Remotingも、その動作のために設定情報が必要です。リモート処理アプリケーションは、プログラムまたは.configファイルを通じて設定することができます。本稿では、.configファイルについて説明します。
.NET Remotingの設定情報は、次のXML形式の<application>
タグ内にまとめて指定されます。
<configuration> <System.Runtime.Remoting> <application> </application> </System.Runtime.Remoting> </configuration>
サーバーアクティブ化オブジェクトを公開する場合は、次の例のような<service>
タグを使います。
<configuration> <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" type="MyObjects.Customer, MyObjects" objectUri="Customer"/> </service> <channels> <channel ref="tcp" port="1234"/> </channels> </application> </system.runtime.remoting> </configuration>
この設定情報ではSingleCall
オブジェクト(完全型名MyObjects.Customer
)を公開しています。このクラスは「MyObjects.DLL」アセンブリに入っており、オブジェクトのURIはCustomerです。ポート1234のTCPチャネルを通じて、このオブジェクトにアクセスできます。
個々のサーバーアクティブ化オブジェクトについて、固有の<wellknown>
タグが必要になります。
クライアント側の対応する.configファイルは次のようになります。
<configuration> <system.runtime.remoting> <application name="MyClient"> <client> <wellknown type="MyObjects.Customer,MyObjects" url="tcp://localhost:1234/Customer"/> </client> <channels> <channel ref="tcp"/> </channels> </application> </system.runtime.remoting> </configuration>
クライアント側の設定ファイルは、サーバー側の設定ファイルと若干異なります。ここでは、<service>
タグの代わりに<client>
タグを使用しています。また、クライアント側の<wellknown>
タグでurl
属性を使用して、サーバーオブジェクトの正確な位置を指定しています。
クライアントアクティブ化オブジェクトの場合は、<wellknown>
タグの代わりに<activated>
タグをサーバーとクライアントの両方で使用します。次の例は、クライアントアクティブ化オブジェクトの公開方法を示しています。
<system.runtime.remoting> <application name="Data"> <service> <activated type="MyObjects.Customer,MyObjects"/> </service> <channels> <channel ref="tcp" port="1234"/> </channels> </application> </system.runtime.remoting> </configuration>
クライアント側の対応する設定ファイルは次のようになります。
<configuration> <system.runtime.remoting> <application name="Data"> <client url="tcp://localhost:1234/Data"> <!-- You can only use one url @ a time --> <activated type="MyObjects.Customer,MyObjects"/> </client> <channels> <channel ref="tcp"/> </channels> </application> </system.runtime.remoting> </configuration>