Tomcat JDBC pool maxActive limits and abandoned connection detection behavior
0 reputation · 06 Dec 2024, 13:48 UTC
0 reputation · 06 Dec 2024, 13:48 UTC
Tomcat JDBC connection pool documents maxActive as the limit for concurrent connections and describes removeAbandoned, abandonedTimeout, minEvictableIdleTimeMillis and logAbandoned as diagnostic controls for pool exhaustion scenarios.
The design question is how these documented limits and controls interact when the goal is to understand intermittent exhaustion without assuming a specific incident or environment.
Uncertainty remains about the ordering and accounting effects of the controls relative to maxActive, and about the observable impact of leak logging when abandonment removal is not enabled.
Does removeAbandoned reclaim a connection against maxActive immediately after abandonedTimeout elapses, or only on the next borrow attempt?
Is logAbandoned=true observable in logs when removeAbandoned is false, and what is the documented relationship between the eviction thread interval minEvictableIdleTimeMillis and abandoned detection?
removeAbandoned does not reclaim a connection the moment abandonedTimeout elapses. Abandoned checks are triggered by borrow attempts (and, in some configurations, the pool's maintenance sweep), not by a per-connection timer that fires independently. And logAbandoned=true without removeAbandoned=true is largely a no-op for leak diagnostics: the stack-trace capture that makes logAbandoned useful happens on the abandoned-removal path, so with removal disabled you should not expect leak stack traces in the logs.
maxActive is the hard ceiling on concurrently checked-out connections, enforced at borrow time before any abandonment logic runs. When the pool is at maxActive, a new borrow waits up to maxWait and then fails. This ordering matters for your design question:
removeAbandoned=true, the borrow path scans checked-out connections and reclaims any whose time since last use exceeds abandonedTimeout (in seconds). The reclaimed connection then counts against maxActive again as available capacity.abandonedTimeout at T+60 may sit unreclaimed until the next contended borrow. Under low traffic, "abandoned" connections can linger well past the timeout.maxActive instantly, exhaustion symptoms can appear before any connection reaches abandonedTimeout, so removal never gets a chance to help. Abandoned detection is a leak mitigation, not an exhaustion cure.The documented behavior is that logAbandoned logs a stack trace (captured at borrow time, so it shows the code that took the connection) when a connection is removed as abandoned. With removeAbandoned=false, that removal path never executes, so the diagnostic output you want generally does not appear. Treat the two flags as a pair: removeAbandoned=true plus logAbandoned=true for leak hunting, with the caveat that stack-trace capture adds overhead on every borrow.
minEvictableIdleTimeMillis belongs to the idle-eviction side of the pool, not the abandoned-detection side. The pool's cleaner thread runs on an interval (timeBetweenEvictionRunsMillis) and evicts connections idle longer than minEvictableIdleTimeMillis, subject to minIdle. This is time-based and runs regardless of borrow activity, but its job is shrinking idle capacity, not reclaiming leaked in-use connections. A connection that the application still holds (a leak) is not "idle" from the evictor's perspective, so idle eviction will not rescue you from leaks — only the abandoned mechanism addresses those, and only when enabled and triggered.
Behavior details have shifted across Tomcat versions, so confirm against the org.apache.tomcat:tomcat-jdbc version you actually run. A quick empirical check:
maxActive=1, removeAbandoned=true, abandonedTimeout=5, logAbandoned=true.Catalina:type=DataSource attributes like numActive) that nothing is reclaimed yet.removeAbandoned=false and confirm no stack trace appears and the second borrow times out.If your observed behavior differs — for example, you see proactive reclamation without a borrow — report your exact Tomcat version, since that would indicate version-specific sweeper behavior worth pinning down.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.