Description
As of now, the request processing queue size of Tomcat can't be adjusted and defaults to an unbounded queue (this is due to the code in org.apache.tomcat.util.net.AbstractEndpoint#createExecutor
).
There are two properties named server.tomcat.accept-count
and server.tomcat.max-connections
but they work on the TCP connection level, and with HTTP/1.1 keep-alive/pipelining and HTTP/2 multiplexing multiple requests onto one connection this doesn't cut it.
We added it for Jetty via this PR where it was decided to not do it for Tomcat as we already have accept-count
and max-connections
.
Right now, out of the box, a Tomcat application which takes 5 second for a response can be easily overwhelmed because the connections pile up in the queue. Even after stopping the load generator, the application takes some time to recover and to clear the queue.
There's a workaround in code:
@Component
@EnableConfigurationProperties(ServerProperties.class)
class MyProtocolHandlerCustomizer implements TomcatProtocolHandlerCustomizer<ProtocolHandler> {
private final ServerProperties serverProperties;
MyProtocolHandlerCustomizer(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public void customize(ProtocolHandler protocolHandler) {
ServerProperties.Tomcat.Threads threads = this.serverProperties.getTomcat().getThreads();
TaskQueue queue = new TaskQueue(100);
ThreadPoolExecutor executor = new ThreadPoolExecutor(threads.getMinSpare(), threads.getMax(), 60000, TimeUnit.MILLISECONDS, queue);
queue.setParent(executor);
protocolHandler.setExecutor(executor);
}
}
This limits the queue to 100. When doing it that way, Tomcat closes the socket immediately when the queue is full.
I think we should reconsider adding a server.tomcat.threads.max-queue-capacity
property. WDYT?