8.3.1 同時実行数制御および実行待ちキュー制御の考え方
アプリケーションサーバのシステムでアプリケーションのスループットを向上させるためには,複数のリクエストを多重処理することが有効です。複数のスレッドで多重にリクエストを処理した方が,単一スレッドで一度に1リクエストずつ処理するのに比べて,多くの場合,スループットを向上させられます。
ただし,入出力処理,排他処理などにボトルネックがあったり,すでに最大スループットに到達していたりする場合は,多重化によるスループットの向上はできません。このため,同時実行数のチューニングは,次の点を確認しながら進めます。
- 入出力処理,排他処理などのボトルネックの排除
-
スレッドを多重化してもCPU利用率が少ないままでスループットが向上しない場合は,アプリケーションのデータベースアクセスなどの入出力処理や排他処理などにボトルネックがあるおそれがあります。この場合は,ボトルネックになっている処理を特定して,排除してからチューニングする必要があります。例えば,データベースアクセス方法をチューニングしたり,排他処理方法を変更したりして,入出力処理,排他処理などのボトルネックを取り除きます。
- 最大スループットの確認
-
リクエストの多重度を大きくしてスレッド数を増やしていくと,スレッド数の増加に伴ってCPUの空き時間が減少し,さらに増やしていくと,ほとんどCPUの空き時間がない状態になります。この状態になると,スレッドを増やしてもスループットは上がりません。
これは,CPUがボトルネックになっている状態であり,マシン単体の性能として,限界に達している状態です。つまり,この時点のスループットが,マシン単体でのアプリケーションの最大スループットになります。
これ以上のスループットを確保したい場合は,CPUやマシン数を増加させるなど,ハードウェアの増強が必要になります。
- 同時実行数制御によるスループットの維持
-
CPUの利用率が飽和した状態で,さらに多重度を大きくしてスレッドを増やした場合,実行可能な状態でCPUが割り当てられないスレッドが増えます。この状態では,スレッド間のロックが競合したり,スレッドのコンテキストスイッチが多発したりするので,スループットが低下するおそれがあります。
また,スレッド数を増やすと,アプリケーションサーバ内ではスレッド数に応じてメモリ使用量が増えます。つまり,スループット低下とメモリ使用量の増加を防ぐためには,スレッド数の増加を実行可能なスレッド数までに制限する必要があります。
同時実行数制御機能を適切に使用することで,最大同時実行数をチューニングして,リクエストの多重度を大きくした場合でも,最大同時実行数分以上のリクエストの実行を待たせることができます。この結果,一時的に過負荷状態が発生したり,負荷のピークの状態になったりしても,高いスループットを維持できます。
- 実行待ちキューサイズの調整
-
アプリケーションサーバに到着したリクエストが同時実行数の上限を超えたとき,リクエストをキューに登録することで,実行中のほかのリクエストの処理が終わるまでそのリクエストを待たせることができます。しかし,ほかのリクエストの処理が終わるまでリクエストを待たせておくためのキューのサイズ(実行待ちキューサイズ)に上限を設定している場合,実行待ちキューが上限に達したあとで到着したリクエストについては,実行待ちキューには登録されないでクライアントにエラーとして返却されます。このため,実行待ちキューに上限を設定する場合は,待たせるキューに必要な数を確保しておく必要があります。
実行待ちキューへのリクエストの登録とエラーの返却の考え方を,次の図に示します。
図8‒2 実行待ちキューへのリクエストの登録とエラーの返却 - ポイント
-
リクエストを実行待ちキューで待たせるのは,一時的な過負荷状態の場合や負荷のピークの場合にエラーが発生するのを防ぐためです。エラーが返却されるのを避けるために実行待ちキューサイズをむやみに増やすのは,本質的な解決にはなりません。同時実行数を増やしたり,必要に応じてCPUやマシン数を増設したりするなどの対処をしてください。
また,クライアント側でタイムアウトを設定している場合は,リクエストが実行待ちキューに登録されてから実際に実行されるまでの時間が掛かり過ぎると,リクエストの実行前にタイムアウトが発生してエラーになるおそれがあります。
このため,実行待ちキューサイズは,最適なサイズに設定してください。
- 階層的なアプリケーションでの最大同時実行数のバランス
-
あるレイヤだけをチューニングして同時実行数を増やしても,システム全体の性能は向上しません。これは,システム全体としての性能は,性能が低いレイヤに制約されてしまうためです。
特定のレイヤだけを最適化したために無意味な設定を含んでしまった例を,次の図に示します。
図8‒3 特定のレイヤだけを最適化したために無意味な設定を含んでしまった例 また,同時実行数を増やすと,実際にはリクエストを処理していないアイドル状態の場合にも,メモリなどのリソースをむだに消費するおそれがあります。
このため,同時実行数を制御する場合には,システム全体を見渡して,適切な同時実行数をそれぞれのレイヤに設定するようにしてください。