Dando uma olhada na fonte de ConnectionPool.java você parece acertar este trecho de código no
borrowConnection()
método: //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;
}
}
Então, de acordo com isso, sua conexão é Null .
O valor de
con
é recuperado na linha:PooledConnection con = idle.poll();
se você rastrear o código, verá
idle
é (dependendo da sua configuração, mas por padrão) FairBlockingQueue
. Você pode verificar a implementação para obter dicas. Em geral, você sempre tem que fechar ResultSets, Declarações e Conexões e as conexões usadas devem ser liberadas corretamente de volta ao pool. Não fazer isso corretamente pode resultar em conexões nunca fechadas => nunca mais disponíveis para reutilização ( "vazamentos" do pool de conexões ).
Sugiro que você construa algum registro detalhado sobre o estado do pool e o monitore para isolar o problema.
Algumas diretrizes do Apache para evitar vazamentos do pool de conexão do banco de dados:
removeAbandoned="true"
conexões de banco de dados abandonadas são removidas e recicladas
removeAbandonedTimeout="60"
defina o número de segundos que uma conexão de banco de dados ficou ociosa antes de ser considerada abandonada
logAbandoned="true"
registre um rastreamento de pilha do código que abandonou os recursos de conexão do banco de dados. Lembre-se de que "o log de conexões abandonadas adiciona sobrecarga para cada empréstimo de conexão porque um rastreamento de pilha deve ser gerado".
Ainda penso em aumentar um pouco o
maxWait
valor (1200, 1500, 1700 - apenas experimente, não haverá diferença nos tempos de resposta da perspectiva do usuário) limpará os casos raros em que você ainda tiver problemas.