先月、私たちはCORBAコンポーネント・モデルについての検討を開始しました。読者はおそらく、このコンポーネント・モデルが備えるべき最も重要な能力の1つが、イベントの処理であることに気付かれたことと思います。別々のコンポーネントからなるシステムを作成するためには、そのモデルに、あるコンポーネントと別のコンポーネントとの間で (それらのコンポーネントを緊密に結合することなく) 相互に呼び出しを送受信できるようにするための、適切なメカニズムが備わっていなければなりません。
私たちは皆、CORBA、DCOM、およびJava RMIという、さまざまな分散コンピューティング・ミドルウェア・モデルに親しんでいます。これらのモデルはいずれも、同期的なメソッド呼び出しモデルをサポートします。このことはつまり、クライアントがサーバーを介してターゲット・オブジェクトの操作を起動し、応答を待つ間そのクライアントがブロックされることを意味します。このモデルは非常な成功を収めてきましたが、欠点もいくつかあります。
- クライアントとサーバーの間で強固な結合が生じます。サーバーが使用不能な場合、クライアントが例外を処理しなければなりません。
- 通信が同期式で行われるため、クライアントはサーバーの処理が終了するまで待たなければなりません。
- 呼び出しは、特定のサーバーをターゲットとして行われます。これは、point-to-point通信アーキテクチャーを構成していることになります。
この制約に対する解決策として、長い間CORBAイベント・サービスが使用されてきました。そして、数多くのCosEvent実装が広く使用可能になっています。これらの実装でサポートされる機能は、非常に多様ですので、まずイベント・サービスから開始して、次にそれを基に、私たちの新しい、改良型の通知サービスに話をすすめていくことにしましょう。
イベントとは、いったいどのようなものなのでしょうか?イベント という用語はプログラム言語の用語として広く使用されていて、率直に言うと多くの意味を担いすぎています。イベントとは、アプリケーションの一部 (すなわちコンポーネント) がアプリケーションの別の部分に通知したいと判断した、状態の変化のことです。イベントはなんらかの出来事ないしオカレンスであり、したがって原子性 という特性を備えています。マウス・クリック、気象衛星のセンサーからの落雷の発生の通知、あるいはEメール・メッセージの到着は、すべてイベントと見なされます。そして、そのイベントに対して対処するために必要な情報を伝達するデータのインスタンスによって、イベント通知が表されます。マウス・クリックはどこで行われたのか?落雷が発生したのはどの座標地点なのか、また、何時に発生したのか?そのEメールは誰にあてて送られたのか?この時点で、私たちにとって以下のことが明らかになります。
- なんらかのオカレンスが私たちのシステムの内部または外部で発生した。
- 私たちには、これらのオカレンスを追跡してオカレンスに関する通知を行うための、内部または外部システム・コンポーネントがある。
- そのイベント情報に関心を持つコンシューマーがいる。
これは、図1のようなものになります。
図1. イベント通知
これが私たちの使い慣れたCORBAメソッド呼び出しとさほど異なるものではないことに注意してください。メソッド呼び出しでは、クライアントがサーバーを呼び出し、サーバーがなんらかの処理を行って応答を戻します。イベント通知はこれよりもさらに分離が進んでいます。イベント通知の提供元は応答を必要としないこともあり、また、イベント・オカレンスは予測不能であって、論理的なプログラム・フローに適合しにくい場合もあります。イベント通知が暗黙的な呼び出し と呼ばれることがあるのは、このためです。コンシューマーが明示的な呼び出しを行うのではなく、データは、コンシューマーに対してプッシュされることによって使用可能になるのです。
コンシューマーがデータの受信側となるためには、なんらかの方法でコンシューマーを登録しなければなりません。この登録の要点は、コンシューマーがなんらかのインターフェースを実装してから、サプライヤーにオブジェクト参照子を渡さなければならない、ということにあります。サプライヤーは、このオブジェクト参照子を使用してコンシューマーにイベント通知を渡すことになります。したがってこれが、メソッド呼び出しのような、明確なルールに基づいた一連の手順であることが分かります。ただし、私たちのイベント通知システムの目標は、同期通信を行わないようにすることです。
よりありがちなシナリオとして、特定のイベントにおけるコンシューマーは唯一ではなかろう、ということがあります。このシナリオについてさらに説明します。扱う対象はイベントですので、関心を持つ複数のものが通知を受け取れるようにサプライヤーを準備する (そしてアプリケーションを構成する) 必要があります。コンシューマーのほうも、複数のイベントに関心を持つことがあります。したがって、イベント通知サプライヤーとイベント通知コンシューマーの間の関係は、多対多関係になります。サプライヤーにとって、可能な多数のコンシューマーの追跡を処理することは、少々重荷になりそうです。ここで、私たちの目標は、サプライヤーとコンシューマーを、イベントの処理に関係するいくつかの管理タスクから切り離すことにあります。
これは、通信パスに中継局を挿入することによって可能です。これは、キュー、ルーター、あるいは私たちがここで使用するチャネル を付け加えることによる、長期間を経て有効性が認められた設計です。このチャネルはサプライヤーからイベント通知を受け入れ、その通知を、関心のあるすべてのコンシューマーに転送します。サプライヤーは、コンシューマーが開示しようと思えばできる、特定のインターフェースから切り離されるようになっていますので、これは非常にうまいやり方です。サプライヤーは、チャネルによって提供される一般的な通信メカニズムだけを扱います。サプライヤーはまた、コンシューマーが通知をどのように解釈するのかということについて、どのような想定も行う必要がなくなります。というわけで、この時点でサプライヤーは完全に独立しますが、コンシューマーは通知を解釈する方法を知らなければなりません。
図2. イベント・チャネル
イベント・チャネルは、接続されているすべてのサプライヤーから受け取ったすべてのイベントを、接続されたすべてのコンシューマーに伝送します。これにより、多対多関係が提供されます。
コールされるインターフェースを誰が実装するのかを正確に識別するために、チャネルにもう1つ手を加える必要があります。私たちが本当に知りたいことは、誰がクライアントとしての役割を果たし、誰がサーバーとしての役割を果たすのか、ということです。私たちはサプライヤーをサーバーであると考えがちですが、以前の記事から、インターフェースの実装者がサーバーであり、クライアントがそのインターフェースへの呼び出しを開始する、ということが分かります。
中継モデルを拡張すると、チャネルはサプライヤーからイベント通知をプルすることにより、クライアントとして機能することができます。また、サプライヤーがイベント通知をチャネルにプッシュするために呼び出すインターフェースを実装することにより、サーバーとしても機能することができます。イベント通知の方向は常に一方向ですが、イベント通知を移動させるための呼び出しの方向は、どちらの向きにもなります。これにより、このモデルはプル・アンド・プッシュ・モデルに向けてさらに改良されます。
図3. プッシュ・アンド・プル・モデル
混合モードの通信を設計するためのインターフェース用語には、多少紛らわしい点があります。仕様書によると、チャネルは「サプライヤーおよびコンシューマーに対するプロキシー」として定義されています。したがって、チャネルはサプライヤーに対してはプロキシー・コンシューマーとして機能し、コンシューマーに対してはプロキシー・サプライヤーとして機能します。この用語の要点は、サプライヤーがチャネル上のProxyConsumer インターフェースとともに作動し、コンシューマーがチャネル上のProxySupplier インターフェースとともに作動する、ということです。ProxyPushConsumer インターフェースはPushConsumer から継承を行い、サプライヤーはこのインターフェースでチャネルのpush() 操作を呼び出し、イベント通知をチャネルに送信します。ProxyPullConsumer インターフェースはPullConsumer から継承を行い、チャネルはサプライヤーのpull() メソッドを呼び出してイベント通知を獲得します。チャネルの反対側では、インターフェースにProxyPushSupplier (これは、チャネルがコンシューマー側でpush() メソッドを呼び出せるようにします)、およびProxyPullSupplier (これは、コンシューマーがチャネルでpull() メソッドを呼び出せるようにします) が含まれています。
これは飛び出して見える絵によく似ています。こうした絵はすべてドットからできています。最初は、カラーの波の集まりのように見えますが、しばらく見ていると、あるイメージが見えてきます。混沌を支配する秩序があるのです。したがって、インターフェースとその用語をしばらく見つめていると、すべてがはっきりとしてくるはずです。
イベント・サービスは、私たちの同期呼び出しモデルに対して行う必要のある、多くの拡張機能を備えています。イベント・サプライヤーをイベント・コンシューマーから切り離せるようにしてくれるのです。中継チャネルを導入することにより、サプライヤーはイベントがコンシューマーに到達するまで待つ必要がなくなり、私たちは非同期通信チャネルをより有効に活用できることになります。最後に、イベント・チャネルの能力にもよりますが、サプライヤーとコンシューマーの間の多対多関係で、イベントのマルチキャストやブロードキャストなどを含むグループ通信能力を得ることができます。
イベント・サービスの成功は、イベント・サービスにとって災いでもありました。イベント・サービスは広く必要とされ、広く使用されているサービスです。企業は自社の実装をライバルよりも便利なものにしようとしますので、イベント・サービスのそれぞれの実装が拡張され、さまざまな追加が行われてきました。それ自体はすばらしいことなのですが、相互運用ができない、多くの異なるイベント・サービスが出来上がってしまいました。解決策は、CORBA 3.0のイベント・サービスを拡張して、このはなはだしい制限のいくつかに対処することです。この拡張イベント・サービスは通知サービスという名前で知られています。これを来月のコラムのテーマにする予定です。
-
OMGのWebサイトに多くのドキュメンテーションと解説が掲載されています。
-
Advanced CORBA Programming with C++、M. HenningおよびS. Vinoski著、Reading, MA. Addison Wesley Longman, Inc. 1999。
-
CORBA 3 Fundamentals and Programming 2nd Ed.、Dr. Jon Siegel著、Wiley, John & Sons, Inc. 1999。
-
Java Programming with CORBA 3rd Ed.、G. Brose、A. Vogel、K. Duddy著、Wiley, John & Sons, Inc. 2001。
-
Object Oriented Concepts, Inc. からOrbacusと通知サービスの実装をダウンロードしてください。
- Javaプログラミングについては、Bruce EckelのMindview.net Webサイト とThinking in Javaの第2版を参照してください。

米国ペンシルベニア州のBerwynに在住するDave Bartlett氏は、コンサルタント、著作家、講演者として活躍中です。「Hands-On CORBA with Java」という 5日間のコースの主催者であり、このコースは公開セッションの形でも、組織内のセミナーの形でも開催されています。現在は、このコースの資料をThinking in CORBA with Java という本にまとめる作業を行っています。Dave氏はペンシルベニア州立大学でエンジニアリングおよびビジネスの修士号を取得しました。ご質問、または特定のトピックに関する興味をお持ちの読者は、dbartlett@pobox.com でDave氏に連絡することができます。