.NET Remoting メモ

WCF目前なのにRemotingをちょっと使ったので調べたことなんかをメモしておきます。あまり詳しくないので、疑って読んでください(-_-;

Remotingは通信手段ではあるけれど、主題は、オブジェクトをサーバとクライアントでやり取りするってとこが要点って感じ。通信の部分は奥深く隠蔽されていて表には出てきません。公開されたオブジェクトのメソッドを呼んだり、その戻り値をもらったりするフレームワークです。プロセス境界やマシン境界を越えて、一つ(に見せかけた)オブジェクトにあんなことやこんなことができます。
奥深〜い技術なのに、おまかせ設定がものっすごい充実してて、従来のソケット通信やら何やらがフルオーダーメイドだとしたら、Remotingは既製品を買って、必要なら丈直しして使うようなイメージ。詳しい中身をよく知らなくてもサンプルを真似るだけであっさり通信できてしまいます。

参考資料

日本語での詳しい書籍は見つけることができなかったけど、ネット上には記事がいろいろあります。
サンプルコードは 猪俣さんの記事 が短くきれいにまとまっています。
古いけど入門には、.NET Remoting Framework の概要.NET リモーティング: 技術概要 あたり。
ちょっと詳しいことは MSDNpatterns&practices の「.NET アプリケーションのパフォーマンスとスケーラビリティの向上」の「第11章 リモート処理パフォーマンスの向上」同「第13章」の一部 (ただし.NET1.1での解説なので.NET2.0の追加機能については触れていない)あたりを参考に。
リモートオブジェクトをインターフェイスを使って作成する方法(個人的に強く推奨)などは CodeZineVisual Studio 2005でのリモーティングに役立つ13のヒント で。
英語では 「Advanced .NET Remoting (2nd Edition)」 のような書籍もあるようです。このサイトの左メニューに .NET Remoting FAQ があります。ちょっと古そうだけど。あとは http://blogs.msdn.com/dotnetremoting/ とか、http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=41&SiteID=1 とか。MSDN TV の.NET2.0での新機能解説も。英語だけどコードやデモを見るだけでも勉強になります。IPC、セキュリティ、バージョン非依存のシリアライズ(OptionalAttributeとか)あたりのデモです。
やっぱり古いけど セキュリティチェックリスト なんかも。

入門以前

MSDN や patterns&practices の解説を読むと、しつこいくらいに本当にRemotingでいいの?みたいなことが書いてます。ASP.NET、Enterprise Services、Remoting から適切なものをきちんと選べってことです。WCF登場でまた変わるのかもしれないですね、って全然知らないで書いてるけど。

Remotingの説明のMSDNライブラリのタイトルが「リモートオブジェクト」なことからわかるように、まずはオブジェクトを共有する技術だってのがポイント。通信技術ではあるけども、1つのオブジェクトがあっち側とこっち側で見えるようにする技術って意識を持つと理解が早いと思います。たぶん。
最初に絵が見たいと思うけど、MSDNは絵が極端に少ないので、patterns&practices の絵がおすすめです。

Remotingを使うには3つのものが必要です。リモート処理可能オブジェクト、サーバ、クライアントの3つ。サーバやクライアントは「特定のアプリケーション モデルを前提としません。Web アプリケーション、コンソール アプリケーション、Windows サービスなど、ほぼすべての種類のプログラムから通信できます。」(MSDNより)だそうで、なんでもOKらしい。

コード例はぐぐれば同じようなものがいくらでも出てきます。つまり、おまかせ設定で使う分にはそれだけでOKってことです。

通信経路

チャネル、フォーマッタなどなど。
チャネルは3種類。HttpChannel、TcpChannel、IpcChannel。IpcChannelは同一マシン内で名前付きパイプを使います。同一マシン内ならIpc。
フォーマッタは2種類。BinaryFormatter、SoapFormatter。SoapFormatterを使う必要があるなら、RemotingじゃなくWebサービスにするほうがMSのおすすめみたいです。patterns&practices の記事によると「データのシリアル化にどのフォーマッタを使うか? - SoapFormatter を使う必要があるなら、.NET リモート処理の代わりに Web サービスを使うことを検討してください。ほとんどの状況において、Web サービスでの SOAP ベースの通信は、パフォーマンス面でリモート処理を上回ります。」だそうで。これでRemotingを使う場面ではフォーマッタは BinaryFormatter 一択です。
シンクってのは通信の階層モデルの各階層をあらわしてると思えばいいのかも。フォーマッタシンクでオブジェクトをシリアライズして、次のトランスポートシンクで転送処理を行います。Remotingはあちこち拡張できるようになってて、中でもユーザが一番拡張することが多いのはシンクでしょうね。ログ取り、フィルタ、独自の暗号化、独自のセキュリティなんかはここに追加するといいようです。
おまかせ設定で使うぶんには、シンクはほとんど意識しません。

リモートオブジェクト

Remotingではオブジェクトをアプリケーションドメイン外に公開します。サーバとクライアント間では、公開されたオブジェクトを通してやりとりします。当然だけど公開するオブジェクトは通信路に乗ってやりとりされるので、無駄を省いた効率的なものにすること。
リモート処理可能オブジェクトには2種類あって、MSDNから引用すると、

  • 値渡しでマーシャリングされるオブジェクト(MBV : Marshal-By-Value) 。これはアプリケーションドメインからコピーされて渡されます。
  • 参照渡しでマーシャリングされるオブジェクト(MBR : Marshal-By-Reference) 。これに対してはプロキシが生成され、クライアントによってオブジェクトへのリモートアクセスに使用されます。

MBVオブジェクトはシリアライズできるオブジェクトってだけなので、[Serializable]属性をつけるとか、独自にシリアライズを実装するとか、それだけです。
MBRはMarshalByRefObjectを継承したオブジェクトを作ればOK。
参考資料で触れた通り interface をサーバとクライアントで dll を使って共有するのがおすすめ。

どっちがいいのか?ってとこは MSDN や patterns&practices を見て検討してください。使い方しだいです。でも多くはMBRかも。

「リモート処理可能オブジェクトとリモート処理不可能オブジェクト」 のあたり、重要な情報が多いのでリンク張っておきます。

アクティベーション

リモートオブジェクトを使う際、オブジェクトの作成と初期化が必要です。何を当然なことを改めてって感じですがw これを「アクティベーション」と呼びます。Remotingではこれが3種類あります。

  • サーバーアクティベーション(SAO) 有効期間がサーバーによって直接制御される
    • SingleCall
    • Singleton
  • クライアントアクティベーション(CAO) (ライフタイムを制御する必要があるときだけ使う、スケーラビリティが制限される)

SAOのSingleCallはクライアントの要求ごとに新しいオブジェクトを生成する。一般的にこれが一番使いやすいハズ。リース期間のシステムはなし。
Singletonはサーバに一つしかないオブジェクトを使う。リース期間がある(無制限、つまりサーバ実行中は開放しないってこともできる)。リソースへの同期取りなどに使う。
CAOはまるでクライアントで生成されたオブジェクトのように振舞う。重たいらしく、あまり使うべきではなさげ。

一般的には SingleCall を使うと思います。たぶん。用途しだいですが。

おもしろいことに、SAOでオブジェクトがサーバに作成されるのは、クライアントがオブジェクトにメソッド呼び出しを実行したときだけで、new や Activator.GetObject を呼び出したときではないそうです。なので、ネットワークでのやり取りが(通常)少なく済みます。対してCAOはクライアントでの生成時にサーバでオブジェクトが生成されて、このとき通信が発生します。

う〜ん、この凝ったアクティベーションを見ると、通信技術っていうよりも「リモートオブジェクト!」って感じですねぇ。

構成

構成ってのは、どのチャネルを使うか、ポート番号/ポート名はどうするか、アクティベーションにはどれを使うかなどの設定のことです。
構成ファイルかプログラムでハードコーディングするか、どちらでもできます。構成ファイルが楽。細かい設定の追加/変更も構成ファイルでできてしまうのがスゴイところ。簡単に使えるようにするためにがんばってるなぁって思います、ハイ。おかげで裏で何がどうなってるのか、よくわかりませんw

その他

パフォーマンスのためには、戻り値がなく(void)、エラーも実行されたかどうかさえもどうでもいいメソッドに [OneWay] 属性を付けたり、非同期でリモート処理を呼び出したりってのもありです。チャッティーにしないでファサードでまとめてアクセスするとか、常道もお忘れなく。

コード例もなしに長い長い説明でした…。お疲れ様です!