Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Problems:
- Q: is there a way to only configure the TaskQueue on the existing handler?
  • Loading branch information
mhalbritter authored and ahmedhus committed Oct 27, 2023
1 parent ec9ac05 commit 2bd5c29
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Map;

import io.undertow.UndertowOptions;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
Expand Down Expand Up @@ -905,6 +906,16 @@ public static class Threads {
*/
private int minSpare = 10;

/**
* idle time in milliseconds
*/
private int maxIdleTime = 60000;

/**
* The maximum number of elements that can queue up before we reject them
*/
private int maxQueueSize = Integer.MAX_VALUE;

public int getMax() {
return this.max;
}
Expand All @@ -921,6 +932,21 @@ public void setMinSpare(int minSpare) {
this.minSpare = minSpare;
}

public int getMaxQueueSize() {
return this.maxQueueSize;
}

public void setMaxQueueSize(int maxQueueSize) {
this.maxQueueSize = maxQueueSize;
}

public int getMaxIdleTime() {
return this.maxIdleTime;
}

public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
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 @@ -36,6 +39,7 @@
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 @@ -90,64 +94,72 @@ public void customize(ConfigurableTomcatWebServerFactory factory) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(properties::getBasedir).to(factory::setBaseDirectory);
map.from(properties::getBackgroundProcessorDelay)
.as(Duration::getSeconds)
.as(Long::intValue)
.to(factory::setBackgroundProcessorDelay);
.as(Duration::getSeconds)
.as(Long::intValue)
.to(factory::setBackgroundProcessorDelay);
customizeRemoteIpValve(factory);
ServerProperties.Tomcat.Threads threadProperties = properties.getThreads();
map.from(threadProperties::getMax)
.when(this::isPositive)
.to((maxThreads) -> customizeMaxThreads(factory, threadProperties.getMax()));
map.from(threadProperties::getMinSpare)
.when(this::isPositive)
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
configureExecutor(factory, threadProperties);
map.from(this.serverProperties.getMaxHttpRequestHeaderSize())
.asInt(DataSize::toBytes)
.when(this::isPositive)
.to((maxHttpRequestHeaderSize) -> customizeMaxHttpRequestHeaderSize(factory, maxHttpRequestHeaderSize));
.asInt(DataSize::toBytes)
.when(this::isPositive)
.to((maxHttpRequestHeaderSize) -> customizeMaxHttpRequestHeaderSize(factory, maxHttpRequestHeaderSize));
map.from(properties::getMaxHttpResponseHeaderSize)
.asInt(DataSize::toBytes)
.when(this::isPositive)
.to((maxHttpResponseHeaderSize) -> customizeMaxHttpResponseHeaderSize(factory, maxHttpResponseHeaderSize));
.asInt(DataSize::toBytes)
.when(this::isPositive)
.to((maxHttpResponseHeaderSize) -> customizeMaxHttpResponseHeaderSize(factory, maxHttpResponseHeaderSize));
map.from(properties::getMaxSwallowSize)
.asInt(DataSize::toBytes)
.to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
.asInt(DataSize::toBytes)
.to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
map.from(properties::getMaxHttpFormPostSize)
.asInt(DataSize::toBytes)
.when((maxHttpFormPostSize) -> maxHttpFormPostSize != 0)
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
.asInt(DataSize::toBytes)
.when((maxHttpFormPostSize) -> maxHttpFormPostSize != 0)
.to((maxHttpFormPostSize) -> customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize));
map.from(properties::getAccesslog)
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
.to((enabled) -> customizeAccessLog(factory));
.when(ServerProperties.Tomcat.Accesslog::isEnabled)
.to((enabled) -> customizeAccessLog(factory));
map.from(properties::getUriEncoding).to(factory::setUriEncoding);
map.from(properties::getConnectionTimeout)
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
map.from(properties::getMaxConnections)
.when(this::isPositive)
.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
.when(this::isPositive)
.to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
map.from(properties::getAcceptCount)
.when(this::isPositive)
.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
.when(this::isPositive)
.to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
map.from(properties::getProcessorCache)
.to((processorCache) -> customizeProcessorCache(factory, processorCache));
.to((processorCache) -> customizeProcessorCache(factory, processorCache));
map.from(properties::getKeepAliveTimeout)
.to((keepAliveTimeout) -> customizeKeepAliveTimeout(factory, keepAliveTimeout));
.to((keepAliveTimeout) -> customizeKeepAliveTimeout(factory, keepAliveTimeout));
map.from(properties::getMaxKeepAliveRequests)
.to((maxKeepAliveRequests) -> customizeMaxKeepAliveRequests(factory, maxKeepAliveRequests));
.to((maxKeepAliveRequests) -> customizeMaxKeepAliveRequests(factory, maxKeepAliveRequests));
map.from(properties::getRelaxedPathChars)
.as(this::joinCharacters)
.whenHasText()
.to((relaxedChars) -> customizeRelaxedPathChars(factory, relaxedChars));
.as(this::joinCharacters)
.whenHasText()
.to((relaxedChars) -> customizeRelaxedPathChars(factory, relaxedChars));
map.from(properties::getRelaxedQueryChars)
.as(this::joinCharacters)
.whenHasText()
.to((relaxedChars) -> customizeRelaxedQueryChars(factory, relaxedChars));
.as(this::joinCharacters)
.whenHasText()
.to((relaxedChars) -> customizeRelaxedQueryChars(factory, relaxedChars));
map.from(properties::isRejectIllegalHeader)
.to((rejectIllegalHeader) -> customizeRejectIllegalHeader(factory, rejectIllegalHeader));
.to((rejectIllegalHeader) -> customizeRejectIllegalHeader(factory, rejectIllegalHeader));
customizeStaticResources(factory);
customizeErrorReportValve(this.serverProperties.getError(), factory);
}

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

private boolean isPositive(int value) {
return value > 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Executor;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Valve;
Expand Down Expand Up @@ -130,16 +131,24 @@ public WebServer getWebServer(HttpHandler httpHandler) {
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
addConnectorExecutor(connector, tomcat);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
addConnectorExecutor(additionalConnector, tomcat);
}
TomcatHttpHandlerAdapter servlet = new TomcatHttpHandlerAdapter(httpHandler);
prepareContext(tomcat.getHost(), servlet);
return getTomcatWebServer(tomcat);
}

private static void addConnectorExecutor(Connector connector, Tomcat tomcat) {
if(connector.getProtocolHandler().getExecutor() instanceof Executor executor) {
tomcat.getService().addExecutor(executor);
}
}

private void configureEngine(Engine engine) {
engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay);
for (Valve valve : this.engineValves) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import jakarta.servlet.http.HttpServletRequest;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Executor;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
Expand Down Expand Up @@ -202,15 +203,23 @@ public WebServer getWebServer(ServletContextInitializer... initializers) {
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
addConnectorExecutor(connector, tomcat);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
addConnectorExecutor(additionalConnector, tomcat);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}

private static void addConnectorExecutor(Connector connector, Tomcat tomcat) {
if(connector.getProtocolHandler().getExecutor() instanceof Executor executor) {
tomcat.getService().addExecutor(executor);
}
}

private void configureEngine(Engine engine) {
engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay);
for (Valve valve : this.engineValves) {
Expand Down

0 comments on commit 2bd5c29

Please sign in to comment.