Skip to content

Commit

Permalink
Use Tomcat's new setter for max queue size
Browse files Browse the repository at this point in the history
Closes gh-41093
Closes gh-40957
Closes gh-40945
  • Loading branch information
mhalbritter committed Jun 20, 2024
1 parent fb9d779 commit e7ffeb3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
import java.util.function.ObjIntConsumer;
import java.util.stream.Collectors;

import javax.management.ObjectName;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.core.StandardThreadExecutor;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.ErrorReportValve;
import org.apache.catalina.valves.RemoteIpValve;
Expand All @@ -39,7 +36,6 @@
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Accesslog;
import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Remoteip;
import org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Threads;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
Expand Down Expand Up @@ -98,7 +94,16 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
.as(Long::intValue)
.to(factory::setBackgroundProcessorDelay);
customizeRemoteIpValve(factory);
configureExecutor(factory, properties.getThreads());
ServerProperties.Tomcat.Threads threadProperties = properties.getThreads();
map.from(threadProperties::getMax)
.when(this::isPositive)
.to((maxThreads) -> customizeMaxThreads(factory, maxThreads));
map.from(threadProperties::getMinSpare)
.when(this::isPositive)
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
map.from(threadProperties::getMaxQueueCapacity)
.when(this::isPositive)
.to((maxQueueCapacity) -> customizeMaxQueueCapacity(factory, maxQueueCapacity));
map.from(this.serverProperties.getMaxHttpRequestHeaderSize())
.asInt(DataSize::toBytes)
.when(this::isPositive)
Expand Down Expand Up @@ -146,23 +151,25 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
customizeErrorReportValve(this.serverProperties.getError(), factory);
}

private void configureExecutor(ConfigurableTomcatWebServerFactory factory, Threads threadProperties) {
factory.addProtocolHandlerCustomizers((handler) -> {
StandardThreadExecutor executor = new StandardThreadExecutor();
executor.setMinSpareThreads(threadProperties.getMinSpare());
executor.setMaxThreads(threadProperties.getMax());
executor.setMaxQueueSize(threadProperties.getMaxQueueCapacity());
if (handler instanceof AbstractProtocol<?> protocol) {
executor.setNamePrefix(ObjectName.unquote(protocol.getName()) + "-exec-");
}
handler.setExecutor(executor);
});
}

private boolean isPositive(int value) {
return value > 0;
}

@SuppressWarnings("rawtypes")
private void customizeMaxThreads(ConfigurableTomcatWebServerFactory factory, int maxThreads) {
customizeHandler(factory, maxThreads, AbstractProtocol.class, AbstractProtocol::setMaxThreads);
}

@SuppressWarnings("rawtypes")
private void customizeMinThreads(ConfigurableTomcatWebServerFactory factory, int minSpareThreads) {
customizeHandler(factory, minSpareThreads, AbstractProtocol.class, AbstractProtocol::setMinSpareThreads);
}

@SuppressWarnings("rawtypes")
private void customizeMaxQueueCapacity(ConfigurableTomcatWebServerFactory factory, int maxQueueCapacity) {
customizeHandler(factory, maxQueueCapacity, AbstractProtocol.class, AbstractProtocol::setMaxQueueSize);
}

@SuppressWarnings("rawtypes")
private void customizeAcceptCount(ConfigurableTomcatWebServerFactory factory, int acceptCount) {
customizeHandler(factory, acceptCount, AbstractProtocol.class, AbstractProtocol::setAcceptCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
package org.springframework.boot.autoconfigure.web.embedded;

import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

import org.apache.catalina.Context;
import org.apache.catalina.Valve;
import org.apache.catalina.core.StandardThreadExecutor;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.ErrorReportValve;
Expand Down Expand Up @@ -572,12 +570,10 @@ void configureExecutor() {
bind("server.tomcat.threads.max=10", "server.tomcat.threads.min-spare=2",
"server.tomcat.threads.max-queue-capacity=20");
customizeAndRunServer((server) -> {
Executor executor = server.getTomcat().getConnector().getProtocolHandler().getExecutor();
assertThat(executor).isInstanceOf(StandardThreadExecutor.class);
StandardThreadExecutor standardThreadExecutor = (StandardThreadExecutor) executor;
assertThat(standardThreadExecutor.getMaxThreads()).isEqualTo(10);
assertThat(standardThreadExecutor.getMinSpareThreads()).isEqualTo(2);
assertThat(standardThreadExecutor.getMaxQueueSize()).isEqualTo(20);
AbstractProtocol<?> protocol = (AbstractProtocol<?>) server.getTomcat().getConnector().getProtocolHandler();
assertThat(protocol.getMaxThreads()).isEqualTo(10);
assertThat(protocol.getMinSpareThreads()).isEqualTo(2);
assertThat(protocol.getMaxQueueSize()).isEqualTo(20);
});
}

Expand Down

0 comments on commit e7ffeb3

Please sign in to comment.