内嵌Tomcat的Spring Boot服务响应阶段千余线程阻塞求助
Hey there, let's break down this thread blocking issue you're facing with your Spring Boot embedded Tomcat setup. Based on the details you shared—1000+ threads getting stuck during response delivery as concurrency rises, paired with a backend Stub that adds 2 seconds of latency—here are the most likely causes and actionable fixes to resolve this:
1. Tomcat Thread Pool Misconfiguration
First up, Tomcat's default thread pool settings aren't built for your 2000-concurrency test. The default maxThreads is only 200, which gets exhausted quickly when threads are tied up waiting for the Stub's 2-second response. This leads to request queues backing up and eventually threads blocking in the response phase as they compete for limited resources.
Fix: Adjust your thread pool parameters in application.properties:
# Increase max threads to account for backend latency (tune based on your server's CPU/memory) server.tomcat.max-threads=1000 # Keep enough spare threads ready to handle sudden traffic spikes server.tomcat.min-spare-threads=200 # Expand the accept queue to hold more requests when the pool is full server.tomcat.accept-count=2000
2. Socket Output Buffer Blocking
If threads are specifically stuck while sending responses (not waiting for the Stub), this usually means Tomcat's socket output buffer is full—your JMeter client isn't receiving data fast enough to keep up with the server's output.
Fix: Tune socket-related settings to reduce write blocking:
# Increase send buffer size to minimize buffer-full events server.tomcat.send-buffer-size=65536 # Set connection timeout to prevent threads from hanging indefinitely server.tomcat.connection-timeout=10000 # For NIO (Tomcat 8's default), adjust selector timeout to keep threads responsive server.tomcat.nio.selector-timeout=1000
3. Blocking Backend Calls Draining Threads
The 2-second delay from your Stub is a critical factor here. Synchronous calls tie up Tomcat threads for the entire duration of the Stub request, quickly depleting the thread pool and leaving no threads to handle new requests or finish sending responses.
Fix: Use asynchronous processing to free up Tomcat threads immediately:
- Add
@EnableAsyncto your main Spring Boot application class to enable async support - Wrap your Stub service call in an async method:
@Service public class StubClient { @Async public CompletableFuture<String> fetchStubData() { // Your existing code to call the 2s-delay Stub goes here return CompletableFuture.completedFuture("Stub response content"); } }
- Return the async result from your controller to let Tomcat release the thread right away:
@RestController public class ApiController { @Autowired private StubClient stubClient; @GetMapping("/your-endpoint") public CompletableFuture<String> handleRequest() { return stubClient.fetchStubData(); } }
This way, Tomcat threads aren't stuck waiting for the Stub—they can handle other requests while the async call runs in the background.
4. JMeter Client-Side Optimizations
Don't overlook the client side! JMeter's configuration can contribute to response-phase blocking:
- Enable HTTP Keep-Alive in your JMeter HTTP Request sampler to reuse connections (reduces connection setup overhead for Tomcat)
- Ramp up threads gradually instead of spawning 2000 at once to avoid overwhelming your server
- Increase JMeter's heap size if it's struggling to handle 2000 concurrent threads
5. Verify the Exact Blocking Point
To confirm where threads are stuck, take a thread dump during the test using the jstack <your-app-pid> command. Look for stack traces pointing to:
java.net.SocketOutputStream.write(): Indicates socket write blocking (client-side slowdown)org.apache.coyote.http11.Http11Processor.service(): Points to thread pool exhaustion from waiting on the backend
6. Consider Upgrading Tomcat
Tomcat 8.5.23 is quite outdated (released in 2017). Check the Tomcat release notes for fixes related to thread blocking or NIO handling in newer 8.5.x patches. Upgrading to a stable newer version (like 8.5.99) might resolve hidden bugs causing the issue.
内容的提问来源于stack exchange,提问作者Wenbin Zhang

