SYSTEM Cited by 1 source
Embedded Tomcat¶
Apache Tomcat as an embedded HTTP + servlet container inside a JVM application — the default in Spring Boot. It uses a blocking-I/O worker model: one thread is held for the full lifetime of a request, blocking on any downstream call.
Blocking-per-request model¶
Per the JDK 21 core docs:
"In our environment, we utilize a blocking model for Tomcat, which in effect holds a worker thread for the lifespan of a request." (Source: sources/2024-07-29-netflix-java-21-virtual-threads-dude-wheres-my-lock)
This is the classical servlet model — simple to reason about, simple to integrate with blocking JDBC / HTTP client libraries, and thread-pool-bound: concurrency ceiling = pool size.
Virtual-thread integration¶
Tomcat 10.1 ships
VirtualThreadExecutor
— a one-line-change executor that replaces the platform-thread
pool with Java 21
virtual threads. See
AbstractEndpoint
for the wire-up.
The model doesn't change: one thread per request. But the thread is now a VT, not a platform thread, so the concurrency ceiling becomes "number of request-shaped VTs the JVM can multiplex over its carrier pool" rather than "size of the platform thread pool".
The Netflix 2024-07-29 failure mode¶
The VT upgrade breaks under
pinning: if request-path
code blocks inside a synchronized block on a shared lock, the
VT pins its carrier thread. On a 4-vCPU host, just 4 such
pinned VTs exhaust all carrier threads. Tomcat keeps accepting
connections + creating request-VTs, but those VTs can't
mount — they sit unmounted in the scheduler queue, holding
the accepted socket. The external symptom:
closeWait socket
accumulation and a 1:1 correspondence with blank-VT count in
the jcmd dump.
"Tomcat accepts a connection on a socket, creates a request along with a virtual thread, and passes this request/thread to the executor for processing. However, the newly created VT cannot be scheduled because all of the OS threads in the fork-join pool are pinned and never released. So these newly created VTs are stuck in the queue, while still holding the socket." (Source: sources/2024-07-29-netflix-java-21-virtual-threads-dude-wheres-my-lock)
Seen in¶
- sources/2024-07-29-netflix-java-21-virtual-threads-dude-wheres-my-lock — Canonical instance of Tomcat's blocking model on VTs breaking under pinning at 4-vCPU-level carrier-pool exhaustion. Also the canonical instance of concepts/closewait-socket-state as a leading indicator of VT carrier-thread exhaustion.
Related¶
- systems/spring-boot — The framework that ships Tomcat embedded.
- systems/java-21-virtual-threads — The VT substrate.
- concepts/virtual-thread — The primitive Tomcat executes on.
- concepts/carrier-thread — The resource exhausted by pinning.
- patterns/blocking-model-per-request-tomcat — Named pattern.
- companies/netflix — Canonical adopter.