2

Tomcatでのフォーム認証には、mysqlでJDBCRealmを使用します。これはほとんどの場合正常に機能します。
(テストで)mysqlデータベースを停止/再起動すると、Tomcat HTTPスレッドの1つが、失敗するのではなく、認証関連のデータを際限なく待機することに気付きます(IOExceptionやタイムアウトなど)。これにより、他のすべてのHTTPスレッドも、共有同期メソッドが必要になるとすぐにブロックされます。その結果、最大数に達するまで、ますます多くのHTTPスレッドが作成され、すべてがブロックされます。
netstatを使用して、ブロックしている接続が事実上失われていることを確認したにもかかわらず、フリーズしたスレッドが起動したりタイムアウトしたりすることはありません。
両側の間にファイアウォールがありますが、これはここでの問題とは何の関係もないと思います。接続は「正常に」セットアップおよび切断されます。
迅速な解決策はもちろん、データベースでTomcatを停止/開始することですが、呼び出しが単に失敗しないのは奇妙に思えます。また、これは同様の状況で本番環境で発生するのではないかと心配しています。
Tomcatを再起動するか、ブロックしているスレッドを手動で強制終了する以外にできることはありますか?
よろしくお願いします。

セットアップ:

  • tomcat6
  • フォーム認証用のJDBCRealm
  • mysql5.5データベース
  • mysql-connector-java-5.1.7-bin.jar

server.xmlの関連部分:

  <Realm className="org.apache.catalina.realm.LockOutRealm" lockOutTime="300">
       <Realm className="org.apache.catalina.realm.JDBCRealm"
            connectionName="xxx"
            connectionPassword="xxx"
            connectionURL="jdbc:mysql://xxx:6446/xxx?autoReconnect=true"
            digest="xxx"
            driverName="com.mysql.jdbc.Driver"
            roleNameCol="xxx"
            userCredCol="xxx"
            userNameCol="xxx"
            userRoleTable="xxx"
            userTable="xxx"
            maxActive="30"
            maxIdle="30"
            maxWait="10000"
            factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"/>
  </Realm>

ブロックされたスレッドの例(「同期された」メソッドの入力時のブロック):

Name: http-8080-60
State: BLOCKED on org.apache.catalina.realm.JDBCRealm@edeb18b owned by: http-8080-61
Total blocked: 27  Total waited: 63

Stack trace: 
 org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:353)
org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:178)
org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:196)
org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:260)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:454)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:394)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Unknown Source)

他のすべてのスレッドでブロックを引き起こしている単一のスレッド(「available()」呼び出しが、もう存在しない接続で待機/ブロックしていることに注意してください):

Name: http-8080-61
State: RUNNABLE
Total blocked: 132  Total waited: 1,198

Stack trace: 
 java.net.PlainSocketImpl.socketAvailable(Native Method)
java.net.PlainSocketImpl.available(Unknown Source)
   - locked java.net.SocksSocketImpl@c679aa4
java.net.SocketInputStream.available(Unknown Source)
com.mysql.jdbc.util.ReadAheadInputStream.available(ReadAheadInputStream.java:231)
com.mysql.jdbc.MysqlIO.clearInputStream(MysqlIO.java:941)
com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1887)
com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101)
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2548)
   - locked java.lang.Object@65d98b58
com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1560)
   - locked java.lang.Object@65d98b58
org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:583)
   - locked org.apache.catalina.realm.JDBCRealm@edeb18b
org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:414)
   - locked org.apache.catalina.realm.JDBCRealm@edeb18b
org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:361)
   - locked org.apache.catalina.realm.JDBCRealm@edeb18b
org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:178)
org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:196)
org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:260)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:454)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:394)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Unknown Source)
4

2 に答える 2

1

を使用してJDBC接続に読み取りタイムアウトを設定してみてくださいsocketTimeout

jdbc:mysql://xxx:6446/xxx?autoReconnect=true&connectTimeout=60000&socketTimeout=60000
于 2013-03-12T13:13:04.870 に答える
1

データベースを認証にのみ使用しますか?DataSourceRealm私見では、とと組み合わせたデータソースを使用する方がよいでしょうLockOutRealm。たぶん、この最後のものはとうまく統合されていませんJDBCRealm

これがJDBCRealmjavadocの抜粋です:

For a Realm implementation that supports connection pooling and doesn't require synchronisation of authenticate(), getPassword(), roles() and getPrincipal() or the ugly connection logic use the DataSourceRealm.

于 2013-03-12T13:25:57.397 に答える