Ta en titt på källan till ConnectionPool.java
du verkar träffa det här kodavsnittet i borrowConnection()
metod:
//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;
}
}
Så enligt detta är din anslutning Null .
Värdet på con
hämtas på raden:
PooledConnection con = idle.poll();
om du spårar koden kommer du att se idle
är (beroende på din konfiguration, men som standard) FairBlockingQueue
. Du kan kolla in implementeringen för tips.
I allmänhet måste du alltid stänga ResultSets, Statements och Connections och använda anslutningar bör släppas tillbaka till poolen på rätt sätt. Om du inte gör det korrekt kan det resultera i att anslutningar aldrig stängts => aldrig mer tillgängliga för återanvändning (anslutningspoolen "läcker" ).
Jag föreslår att du gör en detaljerad loggning över poolens tillstånd och övervakar den för att isolera problemet.
Några riktlinjer från Apache för att förhindra databasanslutningspoolläckor:
removeAbandoned="true"
övergivna databasanslutningar tas bort och återvinns
removeAbandonedTimeout="60"
ställ in antalet sekunder en databasanslutning har varit inaktiv innan den anses vara övergiven
logAbandoned="true"
logga ett stackspår av koden som övergav databasanslutningsresurserna. Tänk på att "loggning av övergivna anslutningar lägger till overhead för varje anslutningslån eftersom en stackspårning måste genereras."
Jag tror fortfarande att maxWait
ökar något värde (1200, 1500, 1700 - bara experimentera, det blir ingen skillnad i svarstiderna ur användarperspektiv) rensar de sällsynta fallen där du fortfarande har problem.