Merge pull request #17871 from htztomic

* pr/17871:
  Polish "Add properties for Jetty threadpool"
  Add properties for Jetty threadpool

Closes gh-17871
This commit is contained in:
Madhura Bhave 2019-08-15 18:32:29 -07:00
commit b853dff014
4 changed files with 104 additions and 0 deletions

View File

@ -62,6 +62,7 @@ import org.springframework.util.unit.DataSize;
* @author Andrew McGhie * @author Andrew McGhie
* @author Rafiullah Hamedy * @author Rafiullah Hamedy
* @author Dirk Deyne * @author Dirk Deyne
* @author HaiTao Zhang
* @since 1.0.0 * @since 1.0.0
*/ */
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
@ -905,6 +906,21 @@ public class ServerProperties {
*/ */
private Integer selectors = -1; private Integer selectors = -1;
/**
* Maximum number of threads.
*/
private Integer maxThreads = 200;
/**
* Minimum number of threads.
*/
private Integer minThreads = 8;
/**
* Maximum thread idle time.
*/
private Integer idleTimeout = 60000;
public Accesslog getAccesslog() { public Accesslog getAccesslog() {
return this.accesslog; return this.accesslog;
} }
@ -933,6 +949,30 @@ public class ServerProperties {
this.selectors = selectors; this.selectors = selectors;
} }
public void setMinThreads(Integer minThreads) {
this.minThreads = minThreads;
}
public Integer getMinThreads() {
return this.minThreads;
}
public void setMaxThreads(Integer maxThreads) {
this.maxThreads = maxThreads;
}
public Integer getMaxThreads() {
return this.maxThreads;
}
public void setIdleTimeout(Integer idleTimeout) {
this.idleTimeout = idleTimeout;
}
public Integer getIdleTimeout() {
return this.idleTimeout;
}
/** /**
* Jetty access log properties. * Jetty access log properties.
*/ */

View File

@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.web.embedded;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.Consumer;
import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory;
@ -29,6 +30,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.cloud.CloudPlatform;
@ -46,6 +49,7 @@ import org.springframework.util.unit.DataSize;
* *
* @author Brian Clozel * @author Brian Clozel
* @author Phillip Webb * @author Phillip Webb
* @author HaiTao Zhang
* @since 2.0.0 * @since 2.0.0
*/ */
public class JettyWebServerFactoryCustomizer public class JettyWebServerFactoryCustomizer
@ -78,6 +82,12 @@ public class JettyWebServerFactoryCustomizer
.addServerCustomizers(new MaxHttpHeaderSizeCustomizer(maxHttpHeaderSize))); .addServerCustomizers(new MaxHttpHeaderSizeCustomizer(maxHttpHeaderSize)));
propertyMapper.from(jettyProperties::getMaxHttpPostSize).asInt(DataSize::toBytes).when(this::isPositive) propertyMapper.from(jettyProperties::getMaxHttpPostSize).asInt(DataSize::toBytes).when(this::isPositive)
.to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, maxHttpPostSize)); .to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, maxHttpPostSize));
propertyMapper.from(jettyProperties::getMaxThreads).when(this::isPositive)
.to((maxThreads) -> customizeThreadPool(factory, (threadPool) -> threadPool.setMaxThreads(maxThreads)));
propertyMapper.from(jettyProperties::getMinThreads).when(this::isPositive)
.to((minThreads) -> customizeThreadPool(factory, (threadPool) -> threadPool.setMinThreads(minThreads)));
propertyMapper.from(jettyProperties::getIdleTimeout).when(this::isPositive).to(
(idleTimeout) -> customizeThreadPool(factory, (threadPool) -> threadPool.setIdleTimeout(idleTimeout)));
propertyMapper.from(properties::getConnectionTimeout).whenNonNull() propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout)); .to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
propertyMapper.from(jettyProperties::getAccesslog).when(ServerProperties.Jetty.Accesslog::isEnabled) propertyMapper.from(jettyProperties::getAccesslog).when(ServerProperties.Jetty.Accesslog::isEnabled)
@ -131,6 +141,15 @@ public class JettyWebServerFactoryCustomizer
}); });
} }
private void customizeThreadPool(ConfigurableJettyWebServerFactory factory, Consumer<QueuedThreadPool> customizer) {
factory.addServerCustomizers((connector) -> {
ThreadPool threadPool = connector.getThreadPool();
if (threadPool instanceof QueuedThreadPool) {
customizer.accept((QueuedThreadPool) threadPool);
}
});
}
private void customizeAccessLog(ConfigurableJettyWebServerFactory factory, private void customizeAccessLog(ConfigurableJettyWebServerFactory factory,
ServerProperties.Jetty.Accesslog properties) { ServerProperties.Jetty.Accesslog properties) {
factory.addServerCustomizers((server) -> { factory.addServerCustomizers((server) -> {

View File

@ -74,6 +74,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Quinten De Swaef * @author Quinten De Swaef
* @author Venil Noronha * @author Venil Noronha
* @author Andrew McGhie * @author Andrew McGhie
* @author HaiTao Zhang
*/ */
class ServerPropertiesTests { class ServerPropertiesTests {
@ -218,6 +219,24 @@ class ServerPropertiesTests {
assertThat(this.properties.getJetty().getSelectors()).isEqualTo(10); assertThat(this.properties.getJetty().getSelectors()).isEqualTo(10);
} }
@Test
void testCustomizeJettyMaxThreads() {
bind("server.jetty.max-threads", "10");
assertThat(this.properties.getJetty().getMaxThreads()).isEqualTo(10);
}
@Test
void testCustomizeJettyMinThreads() {
bind("server.jetty.min-threads", "10");
assertThat(this.properties.getJetty().getMinThreads()).isEqualTo(10);
}
@Test
void testCustomizeJettyIdleTimeout() {
bind("server.jetty.idle-timeout", "10");
assertThat(this.properties.getJetty().getIdleTimeout()).isEqualTo(10);
}
@Test @Test
void testCustomizeUndertowServerOption() { void testCustomizeUndertowServerOption() {
bind("server.undertow.options.server.ALWAYS_SET_KEEP_ALIVE", "true"); bind("server.undertow.options.server.ALWAYS_SET_KEEP_ALIVE", "true");

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConfiguration.ConnectionFactory; import org.eclipse.jetty.server.HttpConfiguration.ConnectionFactory;
import org.eclipse.jetty.server.RequestLog; import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.RequestLogWriter; import org.eclipse.jetty.server.RequestLogWriter;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -49,6 +50,7 @@ import static org.mockito.Mockito.verify;
* *
* @author Brian Clozel * @author Brian Clozel
* @author Phillip Webb * @author Phillip Webb
* @author HaiTao Zhang
*/ */
class JettyWebServerFactoryCustomizerTests { class JettyWebServerFactoryCustomizerTests {
@ -112,6 +114,30 @@ class JettyWebServerFactoryCustomizerTests {
assertThat(logWriter.isAppend()).isFalse(); assertThat(logWriter.isAppend()).isFalse();
} }
@Test
void maxThreadsCanBeCustomized() {
bind("server.jetty.max-threads=100");
JettyWebServer server = customizeAndGetServer();
QueuedThreadPool threadPool = (QueuedThreadPool) server.getServer().getThreadPool();
assertThat(threadPool.getMaxThreads()).isEqualTo(100);
}
@Test
void minThreadsCanBeCustomized() {
bind("server.jetty.min-threads=100");
JettyWebServer server = customizeAndGetServer();
QueuedThreadPool threadPool = (QueuedThreadPool) server.getServer().getThreadPool();
assertThat(threadPool.getMinThreads()).isEqualTo(100);
}
@Test
void idleTimeoutCanBeCustomized() {
bind("server.jetty.idle-timeout=100");
JettyWebServer server = customizeAndGetServer();
QueuedThreadPool threadPool = (QueuedThreadPool) server.getServer().getThreadPool();
assertThat(threadPool.getIdleTimeout()).isEqualTo(100);
}
private CustomRequestLog getRequestLog(JettyWebServer server) { private CustomRequestLog getRequestLog(JettyWebServer server) {
RequestLog requestLog = server.getServer().getRequestLog(); RequestLog requestLog = server.getServer().getRequestLog();
assertThat(requestLog).isInstanceOf(CustomRequestLog.class); assertThat(requestLog).isInstanceOf(CustomRequestLog.class);