Skip to content

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

Last updated · 319 distilled / 1,201 read