ConnectionPool.java
borrowConnection()
でこのコードスニペットをヒットしたようです 方法:
//we didn't get a connection, lets see if we timed out
if (con == null) {
if ((System.currentTimeMillis() - now) >= maxWait) {
throw new SQLException("[" + Thread.currentThread().getName()+"] " +
"Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +
" seconds, none available["+busy.size()+" in use].");
} else {
//no timeout, lets try again
continue;
}
}
したがって、これによると、接続は Null 。
con
の値 次の行で取得されます:
PooledConnection con = idle.poll();
コードを追跡すると、idle
が表示されます is(構成によって異なりますが、デフォルトでは) FairBlockingQueue
。ヒントについては、実装をチェックアウトできます。
一般に、常にResultSets、Statements、およびConnectionsを閉じる必要があり、使用済みの接続はプールに正しく解放される必要があります。正しく行わないと、接続が閉じられず、再利用できなくなる可能性があります(接続プールの「リーク」) 。
プールの状態について詳細なログを作成し、それを監視して問題を特定することをお勧めします。
データベース接続プールのリークを防ぐためのApacheのガイドライン:
removeAbandoned="true"
放棄されたデータベース接続は削除され、リサイクルされます
removeAbandonedTimeout="60"
データベース接続が放棄されたと見なされるまでにアイドル状態になっている秒数を設定します
logAbandoned="true"
データベース接続リソースを放棄したコードのスタックトレースをログに記録します。 「放棄された接続をログに記録すると、スタックトレースを生成する必要があるため、接続を借用するたびにオーバーヘッドが発生する」ことに注意してください。
私はまだmaxWait
を少し増やすと思います 値(1200、1500、1700-実験だけで、ユーザーの観点からは応答時間に違いはありません)は、まだ問題があるまれなケースをクリアします。