Page  1  2  3  4  5  6 

実例で学ぶWebシステムのチューニング手法
IDGジャパン JavaWorld誌2002年2月号特集
「実例で学ぶWebシステムのチューニング手法」の原稿を元に再構成
(埋金 進一・藤野 契)

測定

では、実際に掲示板アプリケーションにJMeterで負荷をかけて、データを取得してみることにする。

まず、負荷クライアント数に対する、レスポンスタイム(Sec)とスループット(PaveView/Sec)の関係を取得してみる。それぞれの測定では、スレッド数と、アプリケーションサーバとデータベース間のJDBCコネクションプール数を変化させてデータを取得する。

変化させるファクタに実行スレッド数とJDBCコネクションプール数を選択した理由は、アプリケーションのロジックによるチューニングを除けば、アプリケーションサーバにとってとしては最も「ボトルネックになりやすい」ポイントであるからだ。しかし、逆にいえば、「最もボトルネックになりやすいポイント」は「最もチューニングの効くポイント」になりうるのである。

一般的に、アプリケーションサーバで、最もパフォーマンスに効くコンフィグレーションパラメータは、

・実行スレッド数
・コネクションプール数

の2点である。

スレッド数

スレッド数は、アプリケーションサーバ内で実際にリクエストの処理に割り当てられ、並行に処理を出来るスレッドの数をあらわす。アプリケーションはこの「スレッド」が割り当てられることにより、処理を行うことが出来るのである。したがって、スレッド数の最適化、スレッドが並行に動けるようなチューニングは、必然的にパフォーマンスに大きな影響を与える。

コネクションプール数

コネクションプールはアプリケーションからデータベースへの接続を高速化する仕組みであり、今日では標準的な技術となっている。

詳細は理論編で述べられているのでそちらを参照いただきたい。詳細は割愛するが、簡単に言うと、コストのかかるコネクション取得処理を、必要になったときに、その都度取得するのではなく、あらかじめ何本かプールしておいて、その中からコネクションを必要とするスレッドに割り当てる、という技術である。

チューニングで扱うパラメータの「コネクションプール数」とは、アプリケーションから使用するために、あらかじめデータベースサーバとの間にプールしておくコネクションの数を指す。コネクションプールの機能は、WebLogic Serverのようにアプリケーションサーバに付属の機能を使うか、JDBC2.0オプションパックであるjavax.sqlパッケージを使うことにより実現できる。今回はWebLogic Serverのコネクションプール機能を使用した。

実行スレッド・コネクションプールという2つのパラメータの他に、WebLogic Serverに特化したパラメータとして、Native I/Oの使用・不使用の設定がある。アプリケーションサーバアプリケーションサーバ依存の設定ではあるが、非常に効くパラメータである。WebLogic Serverを使用する方は覚えておいておくとよいパラメータのひとつだ。詳細については、コラムを参照いただきたい。

ここに挙げた実行スレッド数・コネクションプール数・Native I/Oは、いずれも、WebLogic Serverの設定ファイルであるconfiig.xml直接書き換えるか、WebLogic Serverのコンソール画面からGUIでコンフィグレーションを行うことにより、設定を変更することが出来る。

図14にconfig.xmlの例を示す。config.xmlを直接書き換えることにより設定を行う場合は、設定パラメータのMaxCapacityがコネクションプールの最大値、ThreadCountが実行スレッドの最大値、NativeIOEnabledがNative I/OのON・OFFにあたる。

WebLogic Server6.xでは、config.xmlで設定するほとんど全てのパラメータを、GUIから設定することが出来る。図14がWebLogic Serverコンソール画面のJDBCコネクションプール設定画面である。WebLogic Server自体はたいていの場合、デフォルトの設定で起動することが出来るので一度立ち上げて、設定コンソール画面から細かいコンフィグレーションを行うのも一つの手である。

図14 config.xmlの例

<!--コネクションプールの設定-->
<JDBCConnectionPool
   CapacityIncrement="1"
   DriverName="COM.cloudscape.core.JDBCDriver"
   InitialCapacity="5" 
   MaxCapacity="20" 
: JDBCコネクションの最大値
    Name="samplePool" 
    Properties="user=none;server=none"
    TestConnectionsOnRelease="false" 
    URL="jdbc:cloudscape:samplePool"/>

<!--実行スレッドの設定-->
<ExecuteQueue Name="default"
ThreadCount="5"
:並行に実行できるスレッド数
ThreadPriority="5"/>

<Server
ListenPort="7001"
NativeIOEnabled="true"
:NativeI/Oの有効化
ThreadPoolPercentSocketReaders="33" />

図15 WebLogic Serverコンソール画面(JDBC)

図15
 
 

コラム

■Native I/O

Native I/Oの使用・不使用は、スレッドに関する設定の重要なファクタである。Native I/Oとは、簡単に言うと各OSプラットフォーム用に最適化されたソケットのコントローラである。

JVMのNative I/Oを使用していない場合には、設定したスレッド数のいくつかは、アプリケーションサーバ自体に使用される。実行スレッドのうちに、ソケットからメッセージを読み込む実行スレッドの割合を設定するパラメータがPercentSocketReaderである。基本的にはこのパラメータを増やすことにより、サーバの処理能力は上がるが、このパラメータの最適値は、OSやアプリケーションに依存するため、一概には言えない。

しかし、現在のJVMではほとんどの場合、Native I/Oを使用するほうが、パフォーマンス的によい場合が多い。筆者の経験では、Native I/Oを使用することにより、パフォーマンスが1.5倍強向上するケースもあった。また、Native I/Oを使用することによるバグなどの弊害は最近のJVMではほとんど聞かなくなった。Native I/Oの使用をONにし、PercentSocketReaderの設定を行わない設定をお勧めする(WindowsではデフォルトでNative I/OがONの設定になっている)。今回の測定もNative I/OをONにした状態で行った。

実際に測定する際の注意点であるが、負荷をかけてはじめてから2~3分後から測定を開始するようにする。WEBシステムでは、システムの初期稼動時には安定したパフォーマンスが得られないことが多いためだ。これは、JSPのコンパイルや、初回実行されるときに一度だけロードされるクラスのインスタンス化などに起因することが多い。

では実際の測定結果を見てみよう。

・グラフ1

(実行スレッド:5 コネクション:5)

システムの性能に余裕がある場合には、同時アクセススレッド数に比例して、スループットは線形的に増加し、レスポンスタイムは変化しない。2倍のアクセスがあれば、2倍の秒間ページ閲覧数が得られるのが理想的なのである。

しかし、グラフ1を見るとクライアントスレッドが5から10に変化した時に、スループットは10%程度の伸びしかみせていない。また、レスポンスタイムは、クライアント数に比例してほぼ倍近い値になってしまっている。

このときのCPU使用率は60パーセント程度であった。このことから、WEBシステムは、システムのリソース的には余裕があるのだが、設定スレッド数が少ないため、十分なパフォーマンスを発揮できていない状態であると予想できる。

また、同時アクセスクライアント数が15になったときに、パフォーマンスがやや低下傾向にある。これは、アプリケーションが過負荷時にスムーズに動くことが出来ないためと考えられる。この場合だと、まだまだチューニングの余地が残っているといえる。

グラフ1

・グラフ2

グラフ1の結果より、実行スレッド数が少ないためパフォーマンスが出ないのであろうと推測し、実行スレッドのみを10に増加した時のシステムの挙動を示した図がグラフ2だ。レスポンスタイムは特に変化がないが、スループットは逆にやや落ちている。

これは、実行スレッド数が5のときよりも多くのリクエストをアプリケーションサーバが同時に処理することは出来るのだが、結局DBサーバのコネクション取得でボトルネックが生じているために、全体のパフォーマンスがあがっていないのである。処理速度自体は上がらない一方で、実行スレッドを増やしたことにより、システムのリソースを消費しているために、結果としてグラフ1の実行スレッドが5のときよりもパフォーマンスがやや悪くなっていると予想される。

このときのCPU使用率も60~70%であった。スレッド数が5の時と同様に、アプリケーションサーバの処理能力がネックになって、システムのリソースを活用しきれていないのである。

グラフ1からグラフ2へのチューニング結果は、非常に単純なパターンではあるが、全体のバランスを考えずに、一部をチューニングしたために、結果としてシステム全体のパフォーマンスを落としている一つの例であるといえる。一箇所をチューニングしたらそこが引き金になって、他のボトルネックを生じるというのはよくあるパターンだ。局所的にチューニングをしながらも、常にシステム全体のパフォーマンスを把握することが大切である。

グラフ2

・グラフ3

グラフ2に対して、コネクションプール数を実行スレッドと同じ10に設定し、システムに負荷をかけたときの挙動を示したものがグラフ3である。

クライアントスレッド数を5に設定したときと、10に設定したときでほとんどレスポンスタイムに変化はない((1)の領域)。一方スループットの方は、リクエストの数に対してリニアに増加している。これは、同時にリクエストを出してくるクライアントの数が5~10の状況であれば、サーバの処理能力にまだ余裕があるということを示している。実際、クライアントスレッド数が5の時、サーバのCPU使用率は60~70%であった。

このまま、同時アクセスクライアント数が、50あるいは100になっても、レスポンスタイムは遅くならず、スループットが伸びつづけてくれれば、すばらしいシステムであるが、データベースの更新・参照を行うといった処理のあるアプリケーションではそうはいかない。

更に負荷をかけて、クライアントスレッドが10を超えたあたりでCPUの使用率がほぼ100%になった。同時アクセスクライアントが15になると、スループットは下降をはじめ、レスポンスタイムは遅くなっている様子が見て取れる。このときCPU使用率は100%が続いていた。この掲示板システムは、同時アクセススレッド数が10を超えたあたりが、システムの性能限界点であると予想できる。

グラフ3はWebシステムに負荷をかけたときの典型的な挙動である。理論編の図5-1のグラフに近いことがわかるだろう。ある閾値までは、レスポンスタイムが一定で、スループットは線形的に増加する。しかし、一度閾値を超えると後は一方的にシステムのパフォーマンスは落ちて行くのである。

アプリケーションにCPU使用率が100%になるまで負荷をかけ、システムの性能特性を測定し、スレッド数とコネクションプール数のパラメータに、おおよその最適値を見出すことが出来たらチューニングは次の段階に進む。レスポンスタイムの曲線をより下方向に、スループットの曲線をより上方向に、レスポンスタイム・スループットの値が悪化し始める閾値のポイントをより、右方向(クライアントスレッドが多い方向)に持っていけるように、アプリケーション的、あるいはOSのパラメータなどのリソース的に、チューニングを更に次の段階へと進めていくのだ。

次の段階で、アプリケーションレベル、あるいはOSレベルでチューニングを行った後は、再びスレッド数、コネクションプール数の最適値をチェックする必要がある。この後に行われたチューニングによって、最も高いパフォーマンスの得られる設定値は、更に変化していることは十分に考えられる。理論編にも述べたが、チューニングとはこういったスパイラルな最適化の繰り返しなのでる。

グラフ3

では、スレッド数とコネクションプール数は多ければ多いほどよいのであろうか?答えは「NO」だ。

実行スレッドの設定値を過剰に設定しても、実際に並行に処理できるスレッドの数は、アプリケーションサーバが稼動するマシンの能力に依存するからである。過剰なスレッド数の設定はメモリなどのリソースを必要以上に消費し、結果として、パフォーマンスの低下をもたらす。コネクションプールの最大数の設定についても同様のことが言える。コネクションプールの保持もまた多くのリソースを消費するのである。一般的に、

実行スレッド数=コネクションプールの最大数+α

という設定がよいパフォーマンスをもたらす場合が多い。実行スレッド数とコネクションプール数は1対1でマッピングされるといった意味合いのものではない。しかし、アプリケーションロジックからデータベースコネクションまでが全くシームレスに処理されるような理想的環境であれば、コネクションプール数は実行スレッド数と同じ数必要になるからである。

では、その絶対値はいくつにすればよいのだろうか。筆者の経験上、100ページビュー/秒あるような大規模なサイトでも、実行スレッド・コネクションプールの設定数は多くて40程度だ。中規模程度のサイトでは設定数20前後で最もよいパフォーマンスが得られることが多い。これらは、あくまで目安の値であり、それぞれのアプリケーションに大きく依存する。例えば、外部のソケットを呼び出してしばらくレスポンスを待つような処理が含まれるような場合には、実行スレッドはコネクションプールに対して多く必要になるかもしれないのである。

アプリケーションサーバによってはコネクションプールの数を動的に変化させることが出来る。「立ち上げ時に5本、負荷がかかってきたら最大10本までコネクションプールを作る。」といった設定が可能だ。これにより、低負荷時に無駄にリソースを消費することを防げるのである。WebLogic Serverもそのような機能をもっている。しかし、システムを実際に運用する上では、

最小のコネクションプール数=最大のコネクションプール数

としておくべきである。コネクションプール数を動的に増加させること自体に多くのリソースが費やされるのである。最悪のケースでは、システムが過負荷状態の場合に、コネクションプールの作成自体が不可能になる場合がありうる。この設定は、これらのリスクを避け、安定したパフォーマンスを出すためにとる対策である。

Page  1  2  3  4  5  6 

このサイトについてプライバシーポリシーサイトマップ

お問合わせ

Copyright (C) 2000-2011 UL Systems, Inc. All Rights Reserved.