J2EEのベストプラクティス・トップ10(+2)(後編)

Kyle Brown, Senior Technical Staff Member, IBM Software Services for WebSphere
Keys Botzum, Senior Consulting I/T Specialist, IBM Software Services for WebSphere
Ruth Willenborg, Senior Manager, IBM WebSphere Performance
2004/8/7


 
10. HttpSessionにはビジネス・ロジックに必要な最小限のデータだけを保管すること

主な内容
6.EJBコンポーネントを利用するときは、Session Facadeを常に使うこと
7.ステートフルSession BeanではなくステートレスSession Beanを使うこと
8.CMT(Container Managed Transaction)を使うこと
9.プレゼンテーション手段としてはJSPを最優先に使うこと
10.HttpSessionにはビジネス・ロジックに必要な最小限のデータだけを保管すること
11.WebSphereでは、ダイナミック・キャッシング機能をオンにし、サーブレット・キャッシング・メカニズムを利用すること
12.O/Rマッピングの手段として、まずはCMP Entity Beanを利用し、プログラマーの生産性を高めること

 セッション情報の永続化を行うべし。

 HttpSessionは、分かりやすいAPIを備え簡単に使うことができるため、アプリケーションのセッション情報の保管場所として最適である。ただ残念なことに、HttpSessionは本来「セッション情報を一時的に保持する場所」にすぎないことを忘れている開発者が少なくない。つまり、キャッシュ領域として無制限に利用できるわけではないのだ。実際に、個々のユーザーのHttpSessionに数MBもの膨大なデータを格納しているシステムを数多く見かける。このような設計では、もし1000ユーザーがログインすれば、1GBものメモリ容量をセッション情報のためだけに消費することになる。

 HttpSessionに保持するセッション情報は最小限にとどめるべきであり、さもなければパフォーマンスに影響が生じることになる。2〜4KB以下に抑えておくのがベスト・プラクティスだ。もっとも、厳密な上限があるわけではなく、例えば8KBのセッション情報を保持することも可能ではある。しかし、2KBに抑える場合に比べれば、明らかにパフォーマンスは低下する。セッション情報のサイズに常に気を配り、必要性に乏しいデータのたまり場にならないよう注意すべきである。

 また、よくある間違いとして、簡単に作り直せるデータさえもHttpSessionにキャッシュとして保存しているケースが挙げられる。アプリケーション・サーバでは、HttpSessionを永続化することで、サーバがダウンしてもHttpSessionを復元する仕組みを備えている。逆にいえば、永続化の不要なデータをHttpSessionに保存しておくと、不必要なシリアライズやディスク書き出しが発生し、大きな負荷となるのだ。

 こうしたデータをキャッシュするには、メモリ上のハッシュ・テーブルを利用し、HttpSessionには同テーブルのキーだけを格納しておけばよい。そして、サーバがフェイルオーバーした場合は、新しいサーバ上で元のデータを作り直すのである。この方法について詳しくは、Kyle Brown氏の「Improving HttpSession Performance with Smart Serialization」(IBM DeveloperWorks)を参照してほしい。

 また、HttpSessionの永続化は忘れずに動作させること。さもなければ、トラブルやメンテナンスなど何らかの理由によりサーバが停止した場合に、そのときアクセスしているすべてのユーザーのセッション情報が失われてしまう。これはユーザーにとってかなり不愉快な経験である。ユーザーは、再度ログインを行い、それまでの作業を始めから繰り返さなくてはならない。

 一方、もしHttpSessionの永続化を動作させていれば、ユーザーのセッション情報は自動的にほかのアプリケーション・サーバに引き継がれる。多くのユーザーは、もともとのサーバが停止したことさえ気付かないはずだ。実のところこれは便利な機能で、厄介なバグによって頻繁にクラッシュするものの、HttpSessionの永続化のおかげで十分なサービス品質を維持しているプロダクション・システムも少なくない。

11. WebSphere Applicatioin Serverでは、ダイナミック・キャッシュ機能をオンにし、サーブレット・キャッシングを利用すること

 サーブレットのキャッシングにより、最小限のオーバーヘッドでパフォーマンスを大幅に改善できる。コードの変更も不要である。

 キャッシングは、パフォーマンスを向上する手段として広く利用されている技法だ。しかし残念ながら、現在のJ2EE仕様ではサーブレットやJSPのキャッシュについて規定していない。そこでWASでは、アプリケーションを変更することなくページやフラグメント(ページの一部)のキャッシングを実現する「ダイナミック・キャッシュ機能」を提供している。同機能では、XMLベースのDDファイルを利用して、キャッシュ・ポリシーを宣言的に指定する。よって、アプリケーション自体はJ2EE準拠のポータビリティを維持しつつも、WASに備わるサーブレットおよびJSPのキャッシングによるパフォーマンス最適化のメリットを得られるのである。

 アプリケーションの特性によっては、ダイナミック・キャッシュ機能により劇的な効果を得ることができる。例えば、J. Stan Cox氏とBrian K. Martin氏の「Exploiting Dynamic Caching in WAS 5.0, Part1」(e-Pro Magazine、July/August 2003)では、ある既存のRSS(RDF Site Summary)生成用サーブレットについてダイナミック・キャッシュ機能を適用したところ、数十倍ものパフォーマンス改善が可能になったことが紹介されている。もっとも、この事例では比較的シンプルなサーブレットを対象としているため、より複雑なアプリケーションの場合はここまでの改善は難しいだろう。

 また、このダイナミック・キャッシュ機能に加えて、WASのプラグインであるESIフラグメント・プロセッサや、IBM HTTP ServerのFRCA(Fast Response Cache Accelerator)、Edge Serverキャッシュ機能などを組み合わせれば、さらなるパフォーマンス向上が実現する。特に、読み込みの負荷の割合が大きなサイトでは、これらを活用することで絶大なアドバンテージを得られるはずだ。これらのパフォーマンス最適化について詳しくは、R. Willenborg氏ほかの「Designing WebSphere Application Server for performance: An evolutionary approach」(IBM Systems Journal Volume 43、No. 2、2004)、およびR. Bakalva氏ほかの「WebSphere Dynamic Cache: Improving WebSphere Performance」(IBM Systems Journal、Vol. 43、No. 2、2004)を参照してほしい。

12. O/Rマッピングの手段として、まずはCMP Entity Beanを利用し、生産性を高めること

 アプリケーション・サーバに備わるCMP Entity Beanの最適化機能(先行読み込み、各種キャッシュ・オプション、隔離レベルなど)を利用すべし。その後、Fast Lane Readerパターンなどを適宜導入し、パフォーマンス目標を達成する。

 O/R(Object/Relational)マッピングは、エンタープライズ規模のJavaアプリケーション構築を支える基盤技術である。ほとんどすべてのJ2EEアプリケーションは、何らかの形でO/Rマッピングを必要とする。そこでサーバ・ベンダーは、各種ツールや標準仕様によって広くサポートされているポータブルなO/Rマッピング機能を用意した。それが、EJBのCMP(Container Managed Persistence)機能である。

 CMPが実装され始めたころは、そのパフォーマンスの低さやSQL機能の少なさから、あまり良い評判が得られなかった。しかし、改良の施されたEJB 2.0および2.1仕様が制定され、IBM WebSphere Studio Application Developerをはじめとする対応ツールが登場すると、それまでのCMPの評価は覆されることになった。

 いまや、高いパフォーマンスを要求されるアプリケーションにおいても、CMP Entity Beanが数多く導入されている。それを可能にしたのは、キャッシュのライフタイム管理や先行読み込みなど、アプリケーション・サーバに備わるCMP Entity Beanの最適化機能である。これらの最適化はDDにて指定するため、アプリケーション・コードの変更は不要で、ポータビリティにも影響しない。

 キャッシュのライフタイム管理とは、CMP Entity Beanの内容をキャッシュに保存し、一定時間が経過したらそれを破棄するメカニズムである。これにより、CMP設定の「Option A」と同様のキャッシングによるパフォーマンス向上を実現しつつ、同オプションが苦手とするクラスタリングによるスケールアウトが可能になる。一方、先行読み込みとは、CMR(Container Managed Relationship)と組み合わせて用いる最適化機能である。具体的には、マスター側テーブルを検索する際に、ディテール側テーブルのレコードも先行して取得するメカニズムだ。CMRではマスター側に引き続きディテール側テーブルを検索することが多いため、そうした状況のデータベース・アクセスを最小限に抑えられる。これらの最適化機能とそのパフォーマンス・メリットについて詳しくは、Harvey Gunther氏の「Optimizing WebSphere 5.0 Performance Using EJB 2.0 caching and Read-Ahead hints」(WebSphere Developers Journal、March 2003)を参照してほしい。

 また、CMP Entity Beanの能力を最大限に引き出すには、トランザクションの隔離レベルに留意すべきである。すなわち、データの整合性を維持できる範囲で、可能な限り隔離レベルを低く設定しておく。隔離レベルが低いほどパフォーマンスが向上し、データベースのデッドロックのリスクも抑えられる。

 こうしたCMP Entity Beanの使いこなし方は、最も議論が集中する部分だ。これまでにも、CMP Entity Beanを称賛したり批判したりする記事がいくつも公表されている。ただ、根本的な問題は、データベース開発がそもそも一筋縄ではいかないという点にある。つまり、どのような手段でデータベースを利用するにせよ、データベース検索やレコードのロックの動作についての基礎知識が不可欠だ。よって、CMP Entity Beanを用いる場合は、上述したKyle Brown氏の書籍やRoland Barcia氏ほかの「IBM WebSphere: Enterprise Deployment and Advanced Configuration」(IBM Press、2004)などを参考にして、その扱い方を習得してほしい。ロックやアクセス競合のメカニズムを理解するのは容易ではないが、十分な時間と労力を費やせばマスターは可能だ。

 この記事では、J2EE開発における失敗を避けるためのデザイン・パターンやベスト・プラクティスについて紹介した。これらの実践に必要なすべてを解説できたわけではないが、次に何をすべきかを知るための指針は示せたはずである。

3/3  

 INDEX

Eclipseのカスタマイズの勧め(後編)
  Page1
6.EJBコンポーネントを利用するときは、Session Facadeを常に使うこと
7.ステートフルSession BeanではなくステートレスSession Beanを使うこと
  Page2
8.CMT(Container Managed Transaction)を使うこと
9.プレゼンテーション手段としてはJSPを最優先に使うこと
Page3
10.HttpSessionにはビジネス・ロジックに必要な最小限のデータだけを保管すること
11.WebSphereでは、ダイナミック・キャッシング機能をオンにし、サーブレット・キャッシング・メカニズムを利用すること
12.O/Rマッピングの手段として、まずはCMP Entity Beanを利用し、プログラマーの生産性を高めること


本記事は「IBM developerWorks」に最初に掲載された「The top 10 (more or less) J2EE best practices」をアットマーク・アイティが翻訳したものです。

Java Solution全記事一覧





Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間