APサーバのチューニング項目を知る:J2EEパフォーマンスチューニング(3)(5/6 ページ)
「アプリケーション・サーバを使いJ2EEべースのWebアプリケーションを構築できたのはいいが、どうも本来のパフォーマンスが出ていない」とは、よく聞く話である。本連載では、そういった事態に遭遇した場合に、具体的にどのように対処してパフォーマンスを向上させるかについて解説していく。2回は、「パフォーマンスが出ない!」という場面で、具体的にどのような対処をとったら良いのか、そのオーバービューを紹介しよう。具体的なチューニング手法は、第3回以降で詳細に解説していく。(編集局)
(4)EJB
次に、EJBにおけるパフォーマンスチューニング項目を見ていきます。
EJBには、大きく分類して3つのタイプ(セッションBean、エンティティBean、そしてEJB 2.0で追加されたメッセージ駆動型Bean)があります。それぞれのEJBのタイプごとに役割や性質が異なるため、パフォーマンスに影響を与えるBeanのリソース管理方法や同時アクセス性もタイプによって異なります。各タイプの特性をよく知ることで、性能の引き出し方も見えてきます。
ステートレスセッションBeanのチューニングポイント
ステートレスセッションBeanは、会話ステートを持たないBeanです。1つの処理がステートレスBeanの中で完結して結果を返すような処理に使われます。例えば、現在の株価を返したり、クレジットカードの有効性を検証するサービスなどがそのよい例です。会話ステートを持たないので、クライアントが初回に呼び出したメソッドと、次回呼び出したときのメソッド間での関連はまったくありません。そのためステートレスセッションBeanはステートフルセッションBeanと異なり、あるクライアントに専任するのではなく任意のクライアントに対応します。
上述の特性により、ステートレスセッションBeanインスタンスをプールの中で保持しておき、必要に応じて使い回すというインスタンス管理方法をとることが可能になります。このプールの考え方は、前述の接続プールとよく似ています。プールの中の利用可能なインスタンスを任意のクライアントに対して使い回すことで、リソースを節約し、限られた数のインスタンスで多くの処理をさばくことが可能です。
このインスタンスプールに関連するパラメータをどのように設定するかによって、ステートレスセッションBeanのパフォーマンス性能に差が出る場合があります。
性能改善のポイント
●プール内のステートレスセッションBeanインスタンスの数を最適化しましょう!
■ ステートレスセッションBeanの設定
WLS61固有の設定になるので、weblogic-ejb-jar.xmlに記述します。設定項目は以下のとおりです。
・<initial-beans-in-free-pool>
WLS61起動時、プールに生成するインスタンスの数を指定します。指定しない場合には、起動時生成されるインスタンス数は0です。
・<max-beans-in-free-pool>
プールに生成するインスタンス数の最大値を指定します。デフォルトの設定では、最大値を設定していません。現実的には、同時にサービス提供できるインスタンス数は、スレッド数によって制限されてしまいます。
WLS61のドキュメントでは、<max-beans-in-free-pool>を設定しないよう推奨しています。
<stateless-session-descriptor> <pool> <max-beans-in-free-pool>30</max-beans-in-free-pool> <initial-beans-in-free-pool>5</initial-beans-in-free-pool> </pool> </stateless-session-descriptor>
ステートレスセッションBeanの動作とweblogic-ejb-jar.xmlの関連は以下のとおりです。
- WLS61起動時に、で指定した数のインスタンスが生成されます
- クライアントの要求にこたえるインスタンスの数が十分でない場合、さらにインスタンスが生成されプールに追加されます
- 追加されるインスタンスは、で指定した数で制限されます
- で指定したインスタンスすべてがBusyな状態で、新たな呼び出しがあった場合、処理中のインスタンスに空きが出るまで待たされます
- トランザクションタイムアウト時間が経過した場合には、クライアントにexceptionが戻されます
スステートフルセッションBeanのチューニングポイント
ステートレスセッションBeanと異なり、ステートフルセッションBeanは会話ステートを保持するBeanです。クライアントのメソッド間で会話ステートを保持するために、1つのクライアントに対して1つのステートフルセッションBeanが張り付き(正確にはEJBオブジェクトに対して)、Beanライフサイクルの間専任します。そのためステートレスセッションBeanのように、インスタンスプーリングでスワップするメカニズムは使えません。また、ステートフルセッションBeanは、ステートレスセッションBeanに比べ、会話ステートのやりとりなどにおいて、処理が完了するまでの時間は長くなりがちです。
アクティベーション/パッシベーション
クライアントの数が増える分だけステートフルセッションBeanの数が増えていくのではリソース管理に破たんをきたしてしまいます。そこでステートフルセッションBeanの場合、Beanインスタンスが活動しない間、コンテナがBeanの会話ステートを2次記憶装置に保存し、キャッシュからBeanインスタンスを取り除くことでインスタンスの管理を行っています。この会話ステートをキャッシュから2次記憶装置に保存するメカニズムをパッシベーション、また2次記憶装置からキャッシュに戻すことをアクティベーションと呼んでいます。
キャッシュ内のリソースを適切なレベルに保つために、以下の条件のインスタンスはパッシベートされる候補となります。
- <idle-timeout-seconds>を経過している*1
- 現在メソッドを実行していない
- トランザクションに参加していない
性能改善のポイント
●パッシベーション/アクティベーション処理を減らすよう、キャッシュ内のインスタンス数を最適化しましょう!
■ステートフルセッションBeanの設定
WLS61固有の設定になるので、weblogic-ejb-jar.xmlに記述します。設定項目は以下のとおりです。
・<max-beans-in-cache>
キャッシュに保持可能なステートフルセッションBeanのインスタンス最大数を指定します。
・<idle-timeout-seconds>
指定された時間を経過したインスタンスは、コンテナによってキャッシュから破棄されます。これにより、ステートフルセッションBeanインスタンスがキャッシュに長く居座ることを防ぎます。
記述例は以下のとおりです。
<weblogic-enterprise-bean> <ejb-name>AccountBean</ejb-name> <stateful-session-descriptor> <stateful_session-cache> <max-beans-in-cache>200</max-beans-in-cache> <idle-timeout-seconds>1200</idle-timeout-seconds> </stateful-session-cache> </stateful-session-descriptor> </weblogic-enterprise-bean>
エンティティBeanのチューニングポイント
エンティティBeanは、永続化されたデータのオブジェクトビューを表現します。1つのエンティティBeanインスタンスは、データベースのあるレコード行に対応します。レコード行がそうであるように、エンティティBeanも複数クライアントからの同時アクセスに対応することが求められます。また、データを表現しているので、トランザクションを考慮してデータの完全性も維持しなくてはいけません。エンティティBeanは、データの完全性と同時アクセスの性能という、本来相反する要求を満たさなければならない大変難しい立場にあるBeanであるといえるでしょう。
■エンティティBeanに関する設定
EJBコンテナは、あるタイミングでデータベースからレコードのデータをBeanへ読み出したり(ejbLoad())、またその逆にあるタイミングでBeanのデータをデータベースに保存しようとします(ejbStore())。このときBeanインスタンスとデータベース間でのアクセスが頻繁に発生すると、処理性能の低下を引き起こしてしまいます。データベースへの不要なアクセスを減らすようにすることで、性能の低下を抑えることが可能です。weblogic-ejb-jar.xmlの以下の項目が関連します。
項目 | デフォルト値 | |
---|---|---|
<delay-updates-until-end-of-tx> | true |
上記の設定で、トランザクションコミット時にのみejbStore()を呼び出すように制限されます。不要な更新とejbStore()の呼び出しの反復が回避され、一般にパフォーマンスが向上します。パフォーマンスを重視する場合はデフォルト値のままにしてください。
●読み出し専用(Read-Only)エンティティBean
例えばクライアントからみた場合、データ読み出し専用のBeanインスタンス(外部リソースによって更新される株価表示や商品一覧など)があるとします。このBeanは読み出し専用なので、更新処理(ejbStore())は必要ありません。また、それほど頻繁に更新されないデータであれば、初回にBeanが生成されるときにデータを読み込んでおいて(ejbLoad())、その後のアクセスはキャッシュされたBeanを共有して使用すると、データベース・アクセスを大幅に減らすことができ、エンティティBeanの性能が大幅に向上すると考えられます。
WLS61では、用途に合わせて3つのパターンを選択できます。
項目 | 内容 |
---|---|
Read-Onlyパターン | Beanを読み出し専用にする。ejbStore()は呼び出されないので、更新はできない。EJB作成時に初回のejbLoad()が呼び出され、以後 |
Read-Writeパターン | 通常のRead/Writeパターン |
Read-Mostlyパターン | Read-OnlyパターンとRead-Writeパターンの組み合わせ型。参照系ではRead-Onlyパターンを使用し、更新系ではRead-Writeパターンを使用する |
●同時アクセス方法
前述しましたが、データベースのレコード行がそうであるように、エンティティBeanも同一プライマリキーを持った、異なる複数クライアントからの同時アクセスに対応する必要があります。WLS61では、以下の2つの同時アクセス方法を選択できます。
項目 | 内容 |
---|---|
Exclusive | 異なるクライアントからの同一プライマリキーによるエンティティBeanへのアクセスは直列化されます。データの完全性は保持されますが、パフォーマンスに影響があります。 |
Database (デフォルト) |
異なるクライアントからの同一プライマリキーによるエンティティBeanへのアクセスは、並行処理されます。データの完全性はデータベースに任せられ、衝突が生じた場合には、RDBがトランザクション分離レベルに応じてSQLExceptionをthrowします。 |
デフォルトの設定は以下のとおりです。
項目 | デフォルト値 | 指定値 | |
---|---|---|---|
<concurrency-strategy> | Database | Exclusive | Database | ReadOnly |
性能改善のポイント
●ejbLoad()とejbStore()メソッド呼び出しを抑止し、不要なデータベース・アクセスを減らしましょう!
WLS61では、<concurrency-strategy>で、上述の読み出し専用エンティティBeanの指定も行っています。
●エンティティBeanの設定
今回はWLS61を例に説明していますが、他社のアプリケーション・サーバでも同様の設定が可能だと思われますので、アプリケーション・サーバのドキュメントを調べてみてください。
WLS61固有の設定になるので、weblogic-ejb-jar.xmlに記述します。以下に、記述例を紹介します。AccountBeanクラスを読み取り専用のエンティティBeanとして指定しています。
<weblogic-enterprise-bean> <ejb-name>AccountBean</ejb-name> <entity-descriptor> <entity-cache> <concurrency-strategy>ReadOnly</concurrency-strategy> </entity-cache> </entity-descriptor> </weblogic-enterprise-bean>
Column
EJB2.0の改良点
エンティティBeanを実用的なものにするため、EJB 2.0の仕様では、パフォーマンス向上のため、以下のような工夫が盛り込まれました。
1.メッセージ駆動型Bean
JMSと連携して非同期メッセージングをサポートします。システムによっては、メッセージングのアーキテクチャを同期型(通常、あるクライアントのメソッド処理が終了するまで、その処理はブロックされます)から非同期型に変更することで、大量アクセス処理などにおける処理性能/能力の向上が可能になる場合があります。
2.CMPの拡張
抽象アクセサメソッド(getXXX()、setXXX())が取り入れられ、コンテナが実装クラスを自動生成します。WLS61のCMPコンテナでも最適化について多くの工夫が盛り込まれており、以前のエンティティBeanに比較してかなりパフォーマンスが向上しています。拡張された主なポイントとしては、
- DBアクセスステートメントの生成、およびそのタイミングの最適化
- フィールドグループ定義を利用し、レイジーロードすることでさらに最適化が可能
- インスタンスプール管理の最適化
などが挙げられます。
3.ローカルインターフェイス
同一のEJBコンテナからローカル呼び出しが可能になりました(WLS61では、EJB 2.0を採用する前から同等機能を実装済み)。パフォーマンスを考慮する場合、ローカルインターフェイスの使用が推奨されています。
Copyright © ITmedia, Inc. All Rights Reserved.