Apache⇔Tomcat mod_proxy_ajp連携で「ThreadPool logFull 〜」エラー発生
現象
Tomcatで以下のログを吐き、接続が非常に遅くなる現象が発生した。
org.apache.tomcat.util.threads.ThreadPool logFull 致命的: すべてのスレッド (200) が現在稼働中で待機しています。maxThreads (200) を増やすか、そのサーブレットのステータスを チェックしてください
調査
ひとまずThreadDumpを取る。
結果、以下のようなThreadが大量発生していた。
"TP-Processor176" daemon prio=1 tid=0x09a994b8 nid=0x13ee runnable [0x57a53000..0x57a53db0] at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read1(BufferedInputStream.java:256) at java.io.BufferedInputStream.read(BufferedInputStream.java:313) - locked <0xb043e0f8> (a java.io.BufferedInputStream) at org.apache.jk.common.ChannelSocket.read(ChannelSocket.java:620) at org.apache.jk.common.ChannelSocket.receive(ChannelSocket.java:558) at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:685) at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:889) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:686) at java.lang.Thread.run(Thread.java:595)
同様の現象を説明しているページを発見。
しかし本現象が発生した環境では、Apache側ではmaxClientsを150に設定しているので超えることは無いはずなのだが。
※Apacheの再起動を連発すると、Tomcat側にコネクションが残り続ける?
とにかく何とかする必要がある。
対策
TomcatのAJPコネクタの設定を調査
http://www.oki.com/jp/oss/document/tomcat/tomcat-6.0.14/build/tomcat-docs/config/ajp.html
http://tomcat.apache.org/connectors-doc/generic_howto/timeouts.html
これによるとAJPコネクタのconnectionTimeoutのデフォルト値が無限大に設定されているみたいだ。。。
※HTTPコネクタのconnectionTimeoutのデフォルトは60秒。混同しないように注意。
どうやらこいつを設定してやれば、不要なコネクションが破棄される模様。
server.xmlでデフォルトで設定されているAJPコネクタ設定を
<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
こう修正
<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" connectionTimeout="20000" redirectPort="8443" />
これで不必要なコネクションが解放されるはず。
他のパラメータも調整。
最終的にはこのように設定した。
<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" maxThreads="200" minSpareThreads="25" maxSpareThreads="200" backlog="100" connectionTimeout="20000" enableLookups="false" redirectPort="8443" />