Executorタグは、Tomcatのコンポーネント間を共有できるスレッドプールを表します。
従来、Connector毎にスレッドプールが作成されていましたが、これによりコネクタ間だけでなく
エグゼキュータをサポートするように構成されている他のコンポーネント間でスレッドプールを共有することができます
スレッドプールはJava5から標準利用できるようになったconcurrentパッケージです。
TomcatのコネクタとExecutorはこの仕組みを利用しています。仕組みについては、「Javaプログラム - スレッド - Executors」のnewFixedThreadPoolの概要図をご覧ください。
JVMにおけるThread(即ちTomcatサーバに対するの1リクエストに対する処理)は、Heap領域を処理が終わるまで1リクエスト毎に増えていきます。
Heap領域におけるスレッドの概要に関しては、「Javaプログラム - スレッド - スレッド」のJVMで起きている事の概要図をご覧ください。
executorは、Service要素のネストされた要素です。
そして、それがコネクタに連携されるためには、Executor要素はserver.xmlのConnector要素の前に定義する必要があります。
表記説明:必須可否欄 〇:必須 -:任意
属性 | 必須可否 | 未指定時の デフォルト値 |
初期設定値 | 説明 |
---|---|---|---|---|
className | - | org.apache.catalina.core. StandardThreadExecutor |
未指定 | 実装のクラス。実装では、org.apache.catalina.Executorインタフェースを実装する必要があります。 このインタフェースは、オブジェクトがname属性で参照され、Lifecycleを実装しているため、コンテナで開始および停止できるようにします。 |
name | 〇 | - | tomcatThreedPool 要素はコメント |
Connector要素からexecutor属性でしていされます。Executorのname属性はserver.xml内で一意の名称を付与します。 |
threadPriority | - | 5(NORM_PRIORITY) | 未指定 | (int)executor内のスレッドのスレッド優先順位。 |
daemon | - | true | 未指定 | (boolean)スレッドがデーモンスレッドであるかどうか。 |
namePrefix | - | tomcat-exec- | catalina-exec- | (String)Executorによって作成された各スレッドの名前接頭辞。個々のスレッドのスレッド名は、namePrefix + threadNumber |
maxThreads | - | 200 | 150 | (int)このThreadPool内でアクティブなスレッドの最大数。 |
minSpareThreads | - | 25 | 4 | (int)リクエストの有無に関わらずTomcatサーバに常駐するスレッドの最小数 |
maxIdleTime | - | 60000 | 未指定 | (int)アクティブなスレッドの数がminSpareThreads以下でない限り、アイドル状態のスレッドがシャットダウンするまでのミリ秒数。 |
maxQueueSize | - | 2147483647 | 未指定 | (int)実行を待つ実行可能なタスクの最大数 |
prestartminSpareThreads | - | false | 未指定 | (boolean)Executorの起動時にminSpareThreadsを起動するかどうか。 |
threadRenewalDelay | - | 1000 | 未指定 | (long)ListenerタグにThreadLocalLeakPreventionListenerが設定されている場合、 このexecutorに停止したコンテキストについて通知します。 コンテキストが停止すると、プール内のスレッドが更新されます。 同時にすべてのスレッドを更新しないように、このオプションは2スレッドの更新の間に遅延を設定します。 値はmsで、デフォルト値は1000 msです。値が負の場合、スレッドは更新されません。 |
ConnectorタグもExecutorタグもThreadPool機能を利用して1リクエスト処理(1スレッド)をプール上に管理する事には変わりません。
Connectorタグを2つ用意し、maxThreadsを10 minSpareThreadsを4がそれぞれ指定された例の場合以下のような図になります。
忙しいコネクターのmaxThreadsは10と固定されているので、並列で10のリクエストを捌くことしかできません。
逆に暇なコネクターは、maxThreads10にもいかず、スレッドが縮退して最低数4にまで減りました。
するとポート番号8080のコネクターだけ忙しく、ポート番号8090は有効活用できていません。
このようにコネクター別にリソースを確保するとそれぞれのWebアプリケーション用にきっちりスレッドを確保するメリットはありますが、
アクセス数の差異によってスレッドの確保が足らなくなるケースがでてきます。
Executorを利用することで総和でmaxThreads20個のスレッドが活動できるので8080が忙しい場合には、
そちらのタスクが多くスレッドを活用し、暇な8090も実行しています。
これにより、最大スレッド数が総和で20個を有効利用しています。
ただし、日本のシステムは厳格にそれぞれのスレッドプールを決めている設定の方が多いというのが私の経験則です。
サーバー運用者が多くのConnectorと限られたHeap領域で効率化したい時にExecutorの利用も検討するのが良いでしょうか。