ホーム > 使った

CORBAの概要

ガイド

履歴

editor唯野
2000.2.27公開
2002.11.24修正
2012.1.17修正
2020.2.25文字化け修正

はじめに

ここでは分散オブジェクト志向技術のひとつである CORBA の概要とアプリケーション作成の流れ、そして簡単なサンプル・プログラムの実行までを取り上げています。解説に用いている ORB 実装は VisiBroker for C++ です。本文中におかしな箇所などがあれば、忌憚のないご意見をお聞かせください。

CORBA の概要

CORBA (こるば)とは何か

ひとことでいえば、分散システムのためのフレームワーク。

分散システム

通常のプログラムにおいて、ある処理から別の関数が呼び出されるとき、その関数の実体は同じプログラム中に存在しなければならないが、その実体が他の環境のプログラムにあっても呼び出せるようにしたシステムのことを分散システムという。このとき、関数の呼び出す側をクライアント、呼び出される実体の提供する側をサーバといい、このような両者の間に立って動くソフトウェアのことをミドルウェアと呼ぶ。この分散システムを実現するための仕組みとして Microsoft の COM や Java の RMI、UNIX での RPC などがあるが、CORBA はこれらの中でも最も広範囲かつオープンな仕様という特徴があり、インターネットという一種の分散システムや Java といったツールが広がりをみせる中にあって着実に実績を伸ばしている。

一般にこれらのシステムをゼロから構築しようとすると、目的とする関数の場所の特定や接続のタイミングといった以外にも、接続する相手プログラムの状態把握、異なるシステムとやりとりする場合におけるデータの扱い、エラー発生時の対処など様々な問題を考慮しなければならないため、プログラムは複雑で難解なものとなりやすかった。(あるいは適用できるプラットフォームなどの制限によって実現されることが多かった。)しかしながら CORBA ではその基盤技術としてオブジェクト指向を用いることにより、そういった複雑な仕組みの多くを隠蔽し、また現実味のある仕様を策定することで利用者にとっての分散システムに対する敷居を低くすることに成功している。その結果、CORBA では最小限の手続きを行うだけでリモートメソッドを手軽に呼び出すことができ、それだけ開発者は個々のメソッドの実装(ビジネスロジックの部分)に専念することが可能になっている。

インタフェースとは何か

オブジェクトとインタフェースこれは CORBA に限らずオブジェクト指向そのものにも通じる考え方であるが、あるデータとそれに対する操作をオブジェクトという単位でまとめると「そのオブジェクト同士の間で何のデータがやりとりされるのか」「あるオブジェクトは自分以外のオブジェクトに対して何を受け取り何を渡すのか」というインタフェースが必ず存在している。というよりもオブジェクト指向設計においては、クラスやメソッドもインタフェースという出入口を先に決めておいて後から中身を用意する――ということがいえるためである。中身よりも出入口としてのインタフェースの設計を先行させることによって、オブジェクトの柔軟性の獲得やデータの流れの明確化、ひいてはプログラムの保守性を高めているからである。

もちろん CORBA で定義されるインタフェースとは、CORBA によって呼び出される関数の情報(メソッドのシグネチャ)や CORBA で用いるデータ型・例外の定義を指している。しかしながら、多様な実装形態が予想される分散システムにおいて、特定のプラットフォームや言語に依存したインタフェースの定義では意味を成さない。このため、CORBA では特定の環境に依存しない言語独立な IDL と呼ばれる専用のインタフェース記述言語を用意している。つまり、IDL によって最初のインタフェース定義が行われることにより、複数の実装環境や実装環境の変化に対しても元の定義を変えることなく対応することができる。もっといえば、最初のインタフェースが汎用的なものとして定義されているからこそ、分散システムとしての CORBA の特徴である言語独立・プラットフォーム独立が実現されている。

OMG とは何か

OMG とは CORBA の仕様を策定している業界最大規模の団体のことで、実をいうと CORBA とは OMG が目標に掲げる「分散システムの相互運用での標準」の仕様に対する名称である。(もう少し細かくいうと、OMG の定める OMA という最上位仕様の中のオブジェクト間通信に関する部分を CORBA という。)そして、CORBA の中でも ORB というコンポーネントによってオブジェクト間の実際の通信(位置管理や接続など)が行われている。(即ち、<font color="red">C</font>ommon な <font color="red">ORB</font> の <font color="red">A</font>rchitecture = CORBA。)

このとき書籍などでは CORBA = 仕様ということで、その最上位仕様 = OMA の解説が最初によく引き出されるが、OMA の各要素も CORBA、即ち ORB から見れば「インタフェースを持つ CORBA オブジェクト」という意味では同じなので、あくまでも ORB を中心としたインタフェースのつながりにこそ意味がある。言い換えるならば、そこにあるのは個々のシステムごとの「アプリケーションへのインタフェース」、分散システム全般に汎用的な「サービスへのインタフェース」、特定の分散システムに適用される「ドメイン/ファシリティへのインタフェース」であるといった方が分かりやすい。なぜなら、あくまでも仕様としての CORBA が定めるのは「オブジェクトのインタフェース部分」だからである。

OMA 仕様

VisiBroker とは何か

しかしながら、OMG の大きな特徴のひとつは「OMG は仕様を定めるだけで、それに対する実装は行わない」という点にある。いわば W3C が HTML の仕様だけを定めて、それが IE や NN といった個々のブラウザ(ユーザエージェント)へ反映されるように、CORBA も OMG の仕様をどういうかたちで実装・製品化するかに関しては、個々のベンダの裁量にある。そのため、ひとくちに CORBA 製品(ORB 実装)といっても幅があり、製品間での差別化を図る上での独自機能を持つものが少なくない。一般的にはプラットフォーム独立という特徴を持つ Java をターゲットとした製品が多いが、オブジェクト指向言語の多く(C++、Smalltalk、Ada95)やそれ以外の言語(C、スクリプト言語の一部など)でも CORBA は利用可能になっている。

そういった中にあって VisiBroker は IONA (アイオナ)社の Orbix と並んで最も著名な ORB 実装のひとつで、もとは Visigenic の製品であったものを Borland との合併に伴い Inprise の製品になったものである。VisiBroker は C++ と Java に対応し、それぞれ Windows や主な UNIX 上で動作する。また、Oracle や Sun などのアプリケーションサーバ・ソフトウェアの基盤としても採用されている。

そして、他の ORB 実装と比較した場合における VisiBroker 最大の特徴は Smart Agent と呼ばれる独自プログラムを中心に構成されている点にある。Smart Agent が完全に動的なオブジェクトの位置管理、オブジェクトのライフサイクルの管理、適切な負荷分散などを行うことにより、何よりもシステムへの信頼性(フォールトレランスの実現)と柔軟性の確保が実現されている。(これらの部分は CORBA 2.x における弱点のひとつだった。)また、その他にも VisiBroker は以下のような特徴を持っている。

  • Caffeine (カフェイン)機能
  • (インタフェース定義を前述した IDL ではなく Java でも行える)
  • スマートバインディング
  • (オブジェクトへの接続で最適な通信経路の選択)
  • スレッドプーリング
  • (サーバ側スレッドのリソースをスレッドプールに蓄えて再利用する)
  • コネクション管理
  • (クライアント/サーバ間のコネクション数(接続クライアント数)の適切な管理)
  • IIOP over SSL
  • (SSL 相当のセキュリティ機能)
  • Location Service API と Implementation Repository API
  • (API による VisiBroker の一部機能の直接制御 = カスタマイズ)

CORBA の使われ方

というわけで、以上をまとめると CORBA には次のような特徴がある。

  • オブジェクト指向に基づく分散システムの複雑さの隠蔽
  • インタフェースの先行定義によるオブジェクトの柔軟性・再利用性
  • オブジェクトがどこにあってもよいという位置透過性 (動的な探知も可能)
  • 言語独立・プラットフォーム独立 (様々な言語や環境での実装と運用が可能)

そして、このような環境の異なるオブジェクト間通信の実現されていることを一般に「相互運用性(インターオペラビリティ)がある」というが、CORBA ではこの相互運用性が広い範囲で実現されていることにより、EC 分野でのシステム構築や企業合併における既存システム同士の接続といった用途で強みを発揮している。特に、レガシーシステム(既存資産)を CORBA オブジェクトのひとつとしてラッピングする、コストを抑えたシステム移行において事例が多い。

VisiBroker for C++ におけるアプリケーション開発

ここでは下記の図に従って、VisiBroker for C++ の場合におけるアプリケーション開発の大まかな流れを示す。(つまり、システム分析や設計の段階は省く。)

アプリケーション開発の流れ

1) IDL 定義

前述したように、まず開発者は IDL と呼ばれる言語独立なインタフェース定義言語を用いてインタフェースを定義する。これは C++ でいうところのクラス定義に近く、ここで ORB 間通信を行うオブジェクトのメソッド、ユーザ定義のデータ型・例外などの、いわばプロトタイプを記述する。(逆にいうと IDL でロジックは記述できない。)ここでの定義が汎用的であることによって、逆に様々な言語への置き換え(マッピング)が実現されている。例えば、C++ での int の大きさは処理系に依存するが、それらの違いが IDL では吸収される。IDL ファイルの拡張子は *.idl である。

2) IDL コンパイル

インタフェースが定義されると、次に開発者はそれを実装言語に応じた IDL コンパイラで(コンパイルというよりは)翻訳する。つまり、実際の実装を行う言語が C++ である場合には C++ 用の IDL コンパイラで、言語独立な IDL の内容を C++ 用に置き換える。これによって IDL 定義された内容が C++ のコードとしてマッピングされるので、後の作業は C++ としてのメソッドなりデータ型なり例外として記述できるようになる。VisiBroker for C++ での IDL コンパイラの名前は idl2cpp といい、idl2cpp はコンパイルを行うと図中に示すような 4 つのファイル(*_c.hh、*_c.cc、*_s.hh、*_s.cc)を生成する。

3) クライアントスタブとサーバスケルトン

IDL コンパイルされると、具体的にそれは C++ や Java ではクラスとして展開される。このとき、これのクライアント側コード(*_c.hh/*_c.cc)の集まりのことをクライアントスタブといい、サーバ側コード(*_s.hh/*_s.cc)の集まりのことをサーバスケルトンという。これらは完全な C++ コードなので、後はここに記述されたクラスを基底クラスとして実装クラスを導けばよい。IDL 定義された内容が実装に対する基底クラスへと変換されることにより、実装時に関数のシグネチャを誤ったり不十分な実装クラスを構築するといったミスを事前に防ぐことができる。また、IDL 定義されたメソッドはスケルトンでは純粋仮想関数としてマッピングされるので、これらのクラス内では実装コードを書くことができない。しかし、これも継承という仕組みと組み合わせることにより、インタフェースはそのままに設計(基底クラス)と実装(派生クラス)の分離というプログラム全体での可視性を高めることに成功している。加えて、クライアントとサーバ用のコードが別々に生成される点は、これらの開発を別個に行うことが可能であることを示している。

そして、プログラムの役割分担として、クライアント側でメソッドの呼び出しコードを、サーバ側で呼び出されるメソッドの実体をそれぞれ記述する。その際、適切にスタブやスケルトンをインクルードすることで必要な CORBA の機能へのアクセスが実現される。

4) C++ コンパイル

実装コードが完成したら、後は通常のプログラムと同じように C++ コンパイラでソースファイルをコンパイル・リンクして実行ファイルを生成する。ここでスタブとスケルトンのコードや CORBA のライブラリが実装コードとリンクされてアプリケーションの完成となる。

VisiBroker for C++ から見た CORBA 実行の流れ

このように作成されたアプリケーションが実際の処理においては、どのような流れとして実行されていくのか、その一般的な流れを VisiBroker for C++ の場合として図示すると以下のようになる。

CORBA 実行の流れ

1) リクエスト待ちに入る (サーバ側)

分散システムでは基本的にクライアントからのリクエストを受け付けるために、クライアントより先にサーバが起動していなければならない。(VisiBroker では更にオブジェクトの管理のため Smart Agent を最も先に起動しておく。)

ここでサーバ側のコーディング・イメージを示すと、まず呼び出されるメソッドを実装したサーバのクラスオブジェクトを宣言してから、CORBA を利用するために ORB と BOA (ORB とサーバ実装の間を仲立ちするオブジェクトアダプタ。CORBA 2.2 以前では BOA を使う。)を初期化する。そして、BOA の obj_is_ready( ) の引数に先のクラスオブジェクトを渡すことで、サーバオブジェクトが BOA により CORBA のサーバとして準備される。次いでクライアント側で使われるサーバオブジェクトの情報(オブジェクトリファレンス)をファイルに保存する。最後に impl_is_ready( ) によってサーバ側はクライアント側からのリクエスト待ちループに入る。(いったん impl_is_ready( ) した CORBA サーバはサーバオブジェクトが非活性化されるまで制御を CORBA に譲る = 以降の処理は CORBA がやってくれる。)

2) リクエストを発行する (クライアント側)

同じようにクライアント側コードを概観すると、こちらでも CORBA を使うためにまず ORB を初期化する。次いで(サーバ側に実体のある)メソッドを呼び出すため、サーバオブジェクトが提供するオブジェクトリファレンスを取得する。ここで重要なのはクライアント側にはサーバオブジェクトの実体がないという点にある。そのためクライアント側は呼び出すオブジェクトの実体に替わる何かがなければならない。その元になるのがオブジェクトリファレンスで、そのために取得したオブジェクトリファレンスを目的となるサーバオブジェクトの型へとダウンキャストし(これをナローイングという)、実際のオブジェクトの代わりを務めるプロキシ(代理)オブジェクトを生成している。

すると、これによってサーバオブジェクト(の代理)ができるので、後はそのオブジェクトから普段と同じようにメソッドを呼び出すだけでリクエストの発行を行うことができる。もちろん、このときにはメソッド引数の変換処理(これをマーシャリングという)や相手サーバオブジェクトへの接続などが行われているが、これらは皆 CORBA が行ってくれるので開発者はメソッドを呼び出すコードさえ記述すればよい。

3) リクエストの実行 (サーバ側)

そうしてクライアント側の ORB より送出されたリクエストは、ネットワークプロトコルが TCP/IP の場合には IIOP というプロトコルを用いてサーバ側の ORB へ転送される。リクエストが届くとサーバ側では、リクエストを適切にサーバ環境のものへと変換し(これをアンマーシャリングという)、更に BOA が要求されたサーバ実装と更にその中の実行すべきメソッドの特定を行って(これをディスパッチという)データ(引数)を渡す。こうすることでメソッドの実体での処理が実行される。

4) 結果の返却 (サーバ側 -> クライアント側)

実行されたメソッドが結果(戻り値)を返したら、今度は逆の向きでそれをリプライメッセージとしてクライアント側に返す。この結果、実際にはリモートメソッドの呼び出しであっても、(呼び元にとっては)あたかもローカルメソッドが呼び出されたかのように関数が実行され戻り値も返される。もちろん、呼び出し自体は同期(リターンのあるまで後続処理を遅延する)/非同期(呼び出し後にそのまま自分の処理を継続する)を問わない。

そして、これらの処理中に何らかのエラーが発生すると、それは C++ の例外として送出されるしかけになっている。CORBA の例外には CORBA そのものが用意する標準例外とユーザの定義するユーザ定義例外とがあり、例えば取得したオブジェクトリファレンスが正しくない場合やクライアントが必要とするサーバオブジェクトを発見できない場合などで例外が上げられる。

なお、CORBA でのメソッド呼び出しを大別すると、あらかじめ呼び出すサーバオブジェクトが決定している静的起動と実行時に必要なサーバオブジェクトを探す動的起動とがある。両者はそれぞれ処理のための必要な手続きが異なるが、通常用いられるのは静的起動なので、ここでは静的起動での場合を説明した。

サンプル・プログラムの実行

最後に簡単なアプリケーションの実行を通して CORBA の動作の様子を見てみることにする。このアプリケーションは前節で解説したソース概要に忠実かつ極めてシンプルな構成のものである。詳細は各ソースコードなり同梱の readme.txt に譲るとして、ここではとにかく実行してみることにする。なお、ここで想定する実行環境は VisiBroker for C++ 3.3 (Windows 98)と Borland C++ Builder 4 Enterprise である。

1) make する

サンプルプログラム に必要なファイル一式が収められているので、これを適当に保存・解凍したら、DOS 窓で解凍後のディレクトリへ移動して make する。すると、IDL コンパイル?実行ファイル作成までが行われる。

> make [Enter]

ちなみに、手動で IDL コンパイルを行いたい場合にはコマンドラインより、

> idl2cpp sample.idl [Enter]

とすればよい。また、環境変数のサイズに余裕がないと処理に失敗する。

2) Smart Agent の起動

実行ファイルが作成されたら、まず Smart Agent を起動する。(但し、同一マシン内より実行するのであれば、このサンプルでは必ずしも起動は不要。)

> osagent [Enter]
3) サーバの起動

次いでサーバプログラムを起動する。起動するとクライアントからのリクエスト待ちである旨が表示される。

> server [Enter]
4) クライアントの起動

別の DOS 窓を開き同じディレクトリへ移動したら、今度はクライアントプログラムを起動する。すると、サーバ側で実装されたメソッドがクライアント側より呼び出され処理結果が表示される。(引数として何か数字を与えてください。)

> client 5