Executorタグ

  • Tomcat Version:8.5.23

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要素の前に定義する必要があります。

  • Executorタグ定義数:0~複数

表記説明:必須可否欄 〇:必須 -:任意

属性 必須可否 未指定時の
デフォルト値
初期設定値 説明
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です。値が負の場合、スレッドは更新されません。

Executorタグの考察

ConnectorタグもExecutorタグもThreadPool機能を利用して1リクエスト処理(1スレッド)をプール上に管理する事には変わりません。
Connectorタグを2つ用意し、maxThreadsを10 minSpareThreadsを4がそれぞれ指定された例の場合以下のような図になります。

Executor利用例

忙しいコネクターのmaxThreadsは10と固定されているので、並列で10のリクエストを捌くことしかできません。
逆に暇なコネクターは、maxThreads10にもいかず、スレッドが縮退して最低数4にまで減りました。

するとポート番号8080のコネクターだけ忙しく、ポート番号8090は有効活用できていません。
このようにコネクター別にリソースを確保するとそれぞれのWebアプリケーション用にきっちりスレッドを確保するメリットはありますが、 アクセス数の差異によってスレッドの確保が足らなくなるケースがでてきます。

Executorを利用することで総和でmaxThreads20個のスレッドが活動できるので8080が忙しい場合には、 そちらのタスクが多くスレッドを活用し、暇な8090も実行しています。
これにより、最大スレッド数が総和で20個を有効利用しています。

ただし、日本のシステムは厳格にそれぞれのスレッドプールを決めている設定の方が多いというのが私の経験則です。

サーバー運用者が多くのConnectorと限られたHeap領域で効率化したい時にExecutorの利用も検討するのが良いでしょうか。