特別企画
JDBCはもう不要?
パフォーマンス問題を解決したEJBは
実用期を迎える
田澤孝之
日本BEAシステムズ
2002/12/25
EJB1.1の仕様にはシステムのパフォーマンスを低下させる問題点があり、これが「EJBは遅い」「使えない」というイメージを定着させてしまった。EJB2.0ではようやくこの問題が解決され、さらに開発者にメリットをもたらす仕様が追加されている。本稿では、EJB2.0が解決した従来の問題点とEJB2.0のメリットに触れる。また、本稿をお読みいただくにあたって、EJBの基礎知識のない読者は「Webアプリケーションにおける サーバ・サイドJavaの効果的な利用」(前編 EJBの役割とメリット/後編 EJBのアーキテクチャ)を事前にお読みいただきたい。(編集局) |
■EJB利用の現状
現在サン・マイクロシステムズのサイトでは最新バージョンであるEJB 2.1の仕様がドラフトとして公開されています。EJB 2.1の仕様はJ2EEの1.4に盛り込まれる予定です。詳細はまたの機会にするとして、現時点での最新のバージョンはEJB 2.0、J2EEは1.3です。しかし、2002年12月時点でEJB 2.0を実用レベルで実装しているEJBコンテナはあまりありません。EJB 2.0の仕様は2001年の9月に最終版が出ていることを考えるとEJBコンテナベンダの実装が遅れている事実は否めないでしょう。現在最も利用されているEJBのバージョンはEJB 2.0の1つ前のバージョンであるEJB 1.1です。
EJBは、すでにJ2EEのサーバサイドコンポーネント、ビジネスロジックを実装するための手段として認知されて、さまざまなシステムで利用されるようになってきました。またコンポーネントの流通という観点からも標準化や共通化といった活動をしている団体がいくつかあります。
サンの提供する「Java BluePrints」の「Designing Enterprise Applications with the J2EE Platform」の中でも、さらにはStrutsを代表とするWebクライアントのためのMVC(Model-View-Controller)フレームワークでもビジネスロジックであるモデルはEJBで実装するように推奨されています。「なぜEJBなのか」という議論はもう過去のものであるといえるでしょう。
■EJB 2.0の変更点
まず、EJB 1.1の問題点を分析する前に、EJB 2.0で追加、変更された仕様を以下に紹介します。
メッセージ駆動型Bean コンテナ管理エンティティの改訂 ローカルインターフェイスとローカルホームインターフェイス EJB-QL Selectメソッド ホームメソッド run-asセキュリティ CORBAインタオペラビリティ |
EJB 2.0では新たなEJBであるMDBなども定義されましたが、これらを見てお気付きの方もいらっしゃるでしょう。ほとんどが、EJBコンテナが永続化機構を提供する、コンテナ管理のエンティティBean(CMP)のための仕様の追加や変更になっています。逆をいうと、セッションBeanとBean開発者自身が永続化機構を作りこむ、Bean管理のエンティティBeanに関してはEJB 1.1でほぼ完成形であったことがうかがえるのではないでしょうか。
図1 EJB 2.0の仕様に含まれるEJB 注:EIS(Enterprise Information Sysytem) |
EJBを簡単に復習すると、クライアントとのセッションの間だけ生存する短命なセッションBeanがあります。セッションBeanにはさらに会話状態を保持するものと保持しないものの2種類が存在します。エンティティBeanは長期間存在するオブジェクトを表すEJBです。オブジェクトは永続化されストレージなどに格納されることになります。エンティティBeanにも永続化機構をEJBコンテナが提供するものと開発者が提供するものの2種類が存在します。その中でEJB 2.0で最も手が加えられたのが前者のコンテナ管理永続化のエンティティBean(CMP)です。そして新たにJMSと統合されて非同期処理を実現するメッセージ駆動型Beanが加わりました。
■CMP 1.1の問題点とは
EJB 1.1ではセッションBeanとエンティティBeanの2種類のEJBがありました。EJBはすでにさまざまな方面で利用されていると上述しましたが、厳密にいうと「セッションBeanは利用されているがエンティティBeanの利用は少ない」のが現状なのです。なぜでしょうか? 「EJBは遅い」というコメントを雑誌やWeb上の記事で読まれたことがあると思います。遅いといわれる理由は、エンティティBeanのCMP 1.1の仕様自体が処理速度が出ない仕組みになっている点にありました。
CMP 1.1の仕様では永続先が定められていません。ほとんどのEJBコンテナがサポートしている永続先はRDBとなっています。永続化オブジェクトをRDBに格納したり取り出したりするということは、EJBコンテナが開発者に代わってSQLを発行して実現することになるのですが、コンテナが通常のJDBCプログラミングと比較してSQLを必要以上にRDBに対して発行してしまいます。これは性能に多大な影響を与えます。上述したCMP 2.0に対する仕様の改訂で、それは浮き彫りになっています。以下実際に実装コードを見ながら説明していきます。
エンティティBeanのコンテナ管理フィールド(CMPフィールド)の定義を思い出してください。Beanの実装クラスにCMPフィールドをメンバ変数として定義することになっています。そのメンバ変数に変更を加えるためのアクセサメソッドなどを定義し、リモートインターフェイスに公開することになります。まず以下のBeanのソース(抜粋)を見てください。
public class CustomerBean implements javax.ejb.EntityBean { |
さて、このような実装のCMP 1.1ですが、何がいけなかったのでしょうか。それはCMPフィールドをBeanクラスのインスタンス変数として定義しなければならないという仕様でした。ご存じのとおりCMPはコンテナベンダのツールを利用してコンテナクラスを生成します。永続化ストアへのアクセスはそのコンテナクラスが受け持ちます。生成されたコンテナクラスはデータの整合性保持のためにCMPフィールドをしかるべきタイミングで永続化ストアに正しく格納する義務があります。そこまではいいのですが、親クラスで定義されているインスタンス変数は「いつ」「誰が」変更したのかが、コンテナクラスでは判断できません。そのためにメソッドの呼び出し(トランザクションの開始)ごとに、CMPフィールドを永続化ストアから読み出し、呼び出し終了時に書き出すということをしなければならなかったのです。
つまり、変更の有無を判断できないのでCMPフィールドに変更をしていなくとも、読み出しては書き出すという処理を無条件で実行してしまうのです。これはコンテナベンダには頭の痛い問題でした。もちろんベンダによってはダーティーフラグを用いて書き出しを抑止したり、キャッシュを利用して読み込みを抑止したりというオプションを設けてパフォーマンス対策をしていましたが、根本的な解決にはなっていませんでした。
図2 CMP 1.1でのコンテナクラスの動作 |
■CMP 2.0でどう解決されたか?
それでは、次にCMP 2.0のソース(抜粋)を見てください。
public abstract class CustomerBean implements javax.ejb.EntityBean { |
まずBeanのクラスは抽象(abstract)クラスとして定義をします。そしてこれまでインスタンス変数として定義していたCMPフィールドは抽象アクセサメソッドで定義するように仕様が変更になりました。これでCMP 1.1で持っていた問題がきれいに片付くことになります。コンテナクラスはBeanのクラスを継承して抽象アクセサメソッドの実装をし、実際のCMPフィールドはコンテナクラス内で維持することになります。そのような実装に変わることによってCMPフィールドを「いつ」「誰が」変更したかがはっきりします。「誰」がという点ではコンテナクラス以外では変更をすることができません。要は自分自身です。「いつ」に関してはメソッドが呼ばれたときですがこれも、自身で実装をしているので変更したか、していないかは判断できます。このような仕様の変更により、これまで遅さの原因だったSQLの乱発はCMP 2.0からは抑止されることになりました。
図3 CMP 2.0でのコンテナクラスの動作 |
■EJB 2.0でのメリット
前述したように、EJB 1.1とEJB 2.0の差分はCMPに対するものがほとんどです。これまで仕様が未完成であったことは否めませんが、仕様の中でも特に注目されているEJBがCMPであるというとらえ方もできるのではないでしょうか。なんといっても永続化プログラミングをしなくて済むのですから、どれだけ開発の効率化が図れるでしょうか。また永続化ストアに依存しない抽象化プログラミングも可能になります。
では、そのほかのメリットについても解説していきましょう。
CMRの可能性
コンテナ管理リレーション(CMR)という強力な仕様が追加されました。CMRもそれなりに奥が深いのでここでは簡単に説明しましょう。クラス図を描いていればさまざまな関連が出てくるでしょうし、逆のアプローチでデータスキーマを定義していればテーブル同士の関連が出てくるでしょう。CMRを用いるとそれらをEJBで表現することが容易になります。CMP 2.0はいままでのCMPフィールドに合わせてCMRフィールドが追加されます。CMRフィールドは関連先を表し、1対1、1対nやn対nの関連が表現でき、かつ片方向と双方向の表現ができます。
「顧客が商品を発注する」という至ってシンプルな例を用いて説明します。顧客と発注の関係は1対nの関係を持ち、双方向の関係を持たせることにします。
図4 顧客と発注のクラス図 |
ソース上の定義は簡単です。CMPフィールドと同様にCMRフィールドを定義するのみです。
public abstract class CustomerBean implements javax.ejb.EntityBean { |
ここでは発注(orders)というCMRフィールドを定義してあります。顧客(Customer)オブジェクトが複数の発注(Order)オブジェクトとの関連を持っていることを表しています。EJBの定義をするejb-jar.xmlデプロイメント記述子では、<ejb-relation>要素で関係を定義します。以下にejb-jar.xml(抜粋)を示します。
|
ここでは顧客と発注の関係があり、お互いの方向においてそれぞれ<ejb-relationship-role>要素を定義します。顧客は複数の発注を持つので<cmr-field-name>で定義されるCMRフィールドordersは、<cmr-field-type>でjava.util.Set型と定義されます。逆に発注先の顧客は1つのみとなります。さらに永続化機構の定義としてEJBコンテナに依存したデプロイメント記述子で実際のデータベースのテーブルや外部キーを定義することになります。
このように、顧客オブジェクトから関連する発注オブジェクトを簡単に定義し、クライアントでは簡単に関連先のオブジェクトを取り出すことが可能になります。ここでは本当に簡単に述べましたが、このCMP 2.0での表現の可能性はEJBをさらなるステージに押し上げることでしょう。
ローカルインターフェイスの適用
CMRを利用するにはローカルインターフェイスを利用しなければなりません。これは分散環境をまたがった関連の設定ができないことを意味しています。その点を考えるとローカルインターフェイスはCMRを実現するために設定されたものであるというとらえ方もできます。ローカルインターフェイスはこれまで、呼び出しは値呼び出し(Pass by Value)をしなければならなかったのですが、参照呼び出し(Pass by Reference)が可能になります。結果ネットワーク呼び出しコストと、シリアライゼーションコストがなくなります。
図5 ローカルインターフェイスの概念図 |
これは最適化の一環でEJB 1.1の段階ですでに実装しているコンテナベンダもありましたが、EJB 2.0からは仕様で明確になったわけです。適用には多少考慮しなければなりませんが、これは簡単な話でリモートクライアントに対してどのような機能を公開するかというだけであり、適切な粒度でEJBをクライアントに公開するきっかけにもなり、性能も向上するので適用できる個所にはどんどん適用するべきでしょう。
■まとめ
ざっとEJB 2.0のエッセンスを述べました。これからEJB 2.0を含むJ2EE 1.3の認定アプリケーションサーバ製品が続々と市場に出てくるでしょう。スペースの関係で細かくは説明できませんでしたが、仕様変更による性能の向上と関連を表現できるデザイン上でのメリットはそれまで遅く使い勝手が悪いといわれたエンティティBeanの「常識」を「非常識」とすることでしょう。
2003年、J2EEはCMP 2.0がホットになるかもしれません。そして「さらばJDBCプログラミング」となるかもしれません。
[関連記事]
「Webアプリケーションにおける サーバ・サイドJavaの効果的な利用」(Java Solution)
前編 EJBの役割と基礎
後編 EJBのアーキテクチャ
- 実運用の障害対応時間比較に見る、ログ管理基盤の効果 (2017/5/9)
ログ基盤の構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。今回は、実案件を事例とし、ログ管理基盤の有用性を、障害対応時間比較も交えて紹介 - Chatwork、LINE、Netflixが進めるリアクティブシステムとは何か (2017/4/27)
「リアクティブ」に関連する幾つかの用語について解説し、リアクティブシステムを実現するためのライブラリを紹介します - Fluentd+Elasticsearch+Kibanaで作るログ基盤の概要と構築方法 (2017/4/6)
ログ基盤を実現するFluentd+Elasticsearch+Kibanaについて、構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。初回は、ログ基盤の構築、利用方法について - プログラミングとビルド、Androidアプリ開発、Javaの基礎知識 (2017/4/3)
初心者が、Java言語を使ったAndroidのスマホアプリ開発を通じてプログラミングとは何かを学ぶ連載。初回は、プログラミングとビルド、Androidアプリ開発、Javaに関する基礎知識を解説する。
|
|