Skip to content

Commit 208f581

Browse files
cbo-indeedsnicoll
authored andcommitted
Add 'threads' configuration group for embedded containers
See gh-19475
1 parent 5a687df commit 208f581

File tree

8 files changed

+406
-104
lines changed

8 files changed

+406
-104
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 238 additions & 81 deletions
Large diffs are not rendered by default.

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/JettyWebServerFactoryCustomizer.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ public int getOrder() {
7676
public void customize(ConfigurableJettyWebServerFactory factory) {
7777
ServerProperties properties = this.serverProperties;
7878
ServerProperties.Jetty jettyProperties = properties.getJetty();
79+
ServerProperties.Jetty.Threads threadProperties = jettyProperties.getThreads();
7980
factory.setUseForwardHeaders(getOrDeduceUseForwardHeaders());
80-
factory.setThreadPool(determineThreadPool(jettyProperties));
81+
factory.setThreadPool(determineThreadPool(jettyProperties.getThreads()));
8182
PropertyMapper propertyMapper = PropertyMapper.get();
82-
propertyMapper.from(jettyProperties::getAcceptors).whenNonNull().to(factory::setAcceptors);
83-
propertyMapper.from(jettyProperties::getSelectors).whenNonNull().to(factory::setSelectors);
83+
propertyMapper.from(threadProperties::getAcceptors).whenNonNull().to(factory::setAcceptors);
84+
propertyMapper.from(threadProperties::getSelectors).whenNonNull().to(factory::setSelectors);
8485
propertyMapper.from(properties::getMaxHttpHeaderSize).whenNonNull().asInt(DataSize::toBytes)
8586
.when(this::isPositive).to((maxHttpHeaderSize) -> factory
8687
.addServerCustomizers(new MaxHttpHeaderSizeCustomizer(maxHttpHeaderSize)));
@@ -141,12 +142,12 @@ else if (handler instanceof HandlerCollection) {
141142
});
142143
}
143144

144-
private ThreadPool determineThreadPool(ServerProperties.Jetty properties) {
145-
BlockingQueue<Runnable> queue = determineBlockingQueue(properties.getMaxQueueCapacity());
146-
int maxThreadCount = (properties.getMaxThreads() > 0) ? properties.getMaxThreads() : 200;
147-
int minThreadCount = (properties.getMinThreads() > 0) ? properties.getMinThreads() : 8;
148-
int threadIdleTimeout = (properties.getThreadIdleTimeout() != null)
149-
? (int) properties.getThreadIdleTimeout().toMillis() : 60000;
145+
private ThreadPool determineThreadPool(ServerProperties.Jetty.Threads threadProperties) {
146+
BlockingQueue<Runnable> queue = determineBlockingQueue(threadProperties.getMaxQueueCapacity());
147+
int maxThreadCount = (threadProperties.getMax() > 0) ? threadProperties.getMax() : 200;
148+
int minThreadCount = (threadProperties.getMin() > 0) ? threadProperties.getMin() : 8;
149+
int threadIdleTimeout = (threadProperties.getIdleTimeout() != null)
150+
? (int) threadProperties.getIdleTimeout().toMillis() : 60000;
150151
return new QueuedThreadPool(maxThreadCount, minThreadCount, threadIdleTimeout, queue);
151152
}
152153

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,15 @@ public int getOrder() {
7979
public void customize(ConfigurableTomcatWebServerFactory factory) {
8080
ServerProperties properties = this.serverProperties;
8181
ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
82+
ServerProperties.Tomcat.Threads threadProperties = tomcatProperties.getThreads();
8283
PropertyMapper propertyMapper = PropertyMapper.get();
8384
propertyMapper.from(tomcatProperties::getBasedir).whenNonNull().to(factory::setBaseDirectory);
8485
propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull().as(Duration::getSeconds)
8586
.as(Long::intValue).to(factory::setBackgroundProcessorDelay);
8687
customizeRemoteIpValve(factory);
87-
propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive)
88-
.to((maxThreads) -> customizeMaxThreads(factory, tomcatProperties.getMaxThreads()));
89-
propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
88+
propertyMapper.from(threadProperties::getMax).when(this::isPositive)
89+
.to((maxThreads) -> customizeMaxThreads(factory, threadProperties.getMax()));
90+
propertyMapper.from(threadProperties::getMinSpare).when(this::isPositive)
9091
.to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
9192
propertyMapper.from(this.serverProperties.getMaxHttpHeaderSize()).whenNonNull().asInt(DataSize::toBytes)
9293
.when(this::isPositive)

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ public void customize(ConfigurableUndertowWebServerFactory factory) {
8888
private void mapUndertowProperties(ConfigurableUndertowWebServerFactory factory, FactoryOptions options) {
8989
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
9090
Undertow properties = this.serverProperties.getUndertow();
91+
ServerProperties.Undertow.Threads threadProperties = properties.getThreads();
9192
map.from(properties::getBufferSize).whenNonNull().asInt(DataSize::toBytes).to(factory::setBufferSize);
92-
map.from(properties::getIoThreads).to(factory::setIoThreads);
93-
map.from(properties::getWorkerThreads).to(factory::setWorkerThreads);
93+
map.from(threadProperties::getIo).to(factory::setIoThreads);
94+
map.from(threadProperties::getWorker).to(factory::setWorkerThreads);
9495
map.from(properties::getDirectBuffers).to(factory::setUseDirectBuffers);
9596
map.from(properties::getMaxHttpPostSize).as(DataSize::toBytes).when(this::isPositive)
9697
.to(options.server(UndertowOptions.MAX_ENTITY_SIZE));

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java

Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.net.InetAddress;
2121
import java.net.URI;
2222
import java.nio.charset.StandardCharsets;
23+
import java.time.Duration;
2324
import java.util.Collections;
2425
import java.util.HashMap;
2526
import java.util.Map;
@@ -75,6 +76,7 @@
7576
* @author Andrew McGhie
7677
* @author HaiTao Zhang
7778
* @author Rafiullah Hamedy
79+
* @author Chris Bono
7880
*/
7981
class ServerPropertiesTests {
8082

@@ -207,40 +209,132 @@ void testCustomizeHeaderSizeUseBytesByDefault() {
207209
assertThat(this.properties.getMaxHttpHeaderSize()).isEqualTo(DataSize.ofKilobytes(1));
208210
}
209211

212+
@Test
213+
void testCustomizeTomcatMaxThreads() {
214+
bind("server.tomcat.threads.max", "10");
215+
assertThat(this.properties.getTomcat().getThreads().getMax()).isEqualTo(10);
216+
}
217+
218+
@Deprecated
219+
@Test
220+
void testCustomizeTomcatMaxThreadsDeprecated() {
221+
bind("server.tomcat.maxThreads", "10");
222+
assertThat(this.properties.getTomcat().getMaxThreads()).isEqualTo(10);
223+
// Verify they are locked on same backing props to avoid further downstream
224+
// deprecated testing
225+
assertThat(this.properties.getTomcat().getThreads().getMax()).isEqualTo(10);
226+
}
227+
228+
@Test
229+
void testCustomizeTomcatMinSpareThreads() {
230+
bind("server.tomcat.threads.min-spare", "10");
231+
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
232+
}
233+
234+
@Deprecated
235+
@Test
236+
void testCustomizeTomcatMinSpareThreadsDeprecated() {
237+
bind("server.tomcat.min-spare-threads", "10");
238+
assertThat(this.properties.getTomcat().getMinSpareThreads()).isEqualTo(10);
239+
// Verify they are locked on same backing props to avoid further downstream
240+
// deprecated testing
241+
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
242+
}
243+
210244
@Test
211245
void testCustomizeJettyAcceptors() {
246+
bind("server.jetty.threads.acceptors", "10");
247+
assertThat(this.properties.getJetty().getThreads().getAcceptors()).isEqualTo(10);
248+
}
249+
250+
@Deprecated
251+
@Test
252+
void testCustomizeJettyAcceptorsDeprecated() {
212253
bind("server.jetty.acceptors", "10");
213254
assertThat(this.properties.getJetty().getAcceptors()).isEqualTo(10);
255+
// Verify they are locked on same backing props to avoid further downstream
256+
// deprecated testing
257+
assertThat(this.properties.getJetty().getThreads().getAcceptors()).isEqualTo(10);
214258
}
215259

216260
@Test
217261
void testCustomizeJettySelectors() {
262+
bind("server.jetty.threads.selectors", "10");
263+
assertThat(this.properties.getJetty().getThreads().getSelectors()).isEqualTo(10);
264+
}
265+
266+
@Deprecated
267+
@Test
268+
void testCustomizeJettySelectorsDeprecated() {
218269
bind("server.jetty.selectors", "10");
219270
assertThat(this.properties.getJetty().getSelectors()).isEqualTo(10);
271+
// Verify they are locked on same backing props to avoid further downstream
272+
// deprecated testing
273+
assertThat(this.properties.getJetty().getThreads().getSelectors()).isEqualTo(10);
220274
}
221275

222276
@Test
223277
void testCustomizeJettyMaxThreads() {
224-
bind("server.jetty.max-threads", "10");
278+
bind("server.jetty.threads.max", "10");
279+
assertThat(this.properties.getJetty().getThreads().getMax()).isEqualTo(10);
280+
}
281+
282+
@Deprecated
283+
@Test
284+
void testCustomizeJettyMaxThreadsDeprecated() {
285+
bind("server.jetty.maxThreads", "10");
225286
assertThat(this.properties.getJetty().getMaxThreads()).isEqualTo(10);
287+
// Verify they are locked on same backing props to avoid further downstream
288+
// deprecated testing
289+
assertThat(this.properties.getJetty().getThreads().getMax()).isEqualTo(10);
226290
}
227291

228292
@Test
229293
void testCustomizeJettyMinThreads() {
230-
bind("server.jetty.min-threads", "10");
294+
bind("server.jetty.threads.min", "10");
295+
assertThat(this.properties.getJetty().getThreads().getMin()).isEqualTo(10);
296+
}
297+
298+
@Deprecated
299+
@Test
300+
void testCustomizeJettyMinThreadsDeprecated() {
301+
bind("server.jetty.minThreads", "10");
231302
assertThat(this.properties.getJetty().getMinThreads()).isEqualTo(10);
303+
// Verify they are locked on same backing props to avoid further downstream
304+
// deprecated testing
305+
assertThat(this.properties.getJetty().getThreads().getMin()).isEqualTo(10);
232306
}
233307

234308
@Test
235309
void testCustomizeJettyIdleTimeout() {
310+
bind("server.jetty.threads.idle-timeout", "10s");
311+
assertThat(this.properties.getJetty().getThreads().getIdleTimeout()).isEqualTo(Duration.ofSeconds(10));
312+
}
313+
314+
@Deprecated
315+
@Test
316+
void testCustomizeJettyIdleTimeoutDeprecated() {
236317
bind("server.jetty.thread-idle-timeout", "10s");
237-
assertThat(this.properties.getJetty().getThreadIdleTimeout()).hasSeconds(10);
318+
assertThat(this.properties.getJetty().getThreadIdleTimeout()).isEqualTo(Duration.ofSeconds(10));
319+
// Verify they are locked on same backing props to avoid further downstream
320+
// deprecated testing
321+
assertThat(this.properties.getJetty().getThreads().getIdleTimeout()).hasSeconds(10);
238322
}
239323

240324
@Test
241325
void testCustomizeJettyMaxQueueCapacity() {
326+
bind("server.jetty.threads.max-queue-capacity", "5150");
327+
assertThat(this.properties.getJetty().getThreads().getMaxQueueCapacity()).isEqualTo(5150);
328+
}
329+
330+
@Deprecated
331+
@Test
332+
void testCustomizeJettyMaxQueueCapacityDeprecated() {
242333
bind("server.jetty.max-queue-capacity", "5150");
243334
assertThat(this.properties.getJetty().getMaxQueueCapacity()).isEqualTo(5150);
335+
// Verify they are locked on same backing props to avoid further downstream
336+
// deprecated testing
337+
assertThat(this.properties.getJetty().getThreads().getMaxQueueCapacity()).isEqualTo(5150);
244338
}
245339

246340
@Test
@@ -257,6 +351,38 @@ void testCustomizeUndertowSocketOption() {
257351
"true");
258352
}
259353

354+
@Test
355+
void testCustomizeUndertowIoThreads() {
356+
bind("server.undertow.threads.io", "4");
357+
assertThat(this.properties.getUndertow().getThreads().getIo()).isEqualTo(4);
358+
}
359+
360+
@Deprecated
361+
@Test
362+
void testCustomizeUndertowIoThreadsDeprecated() {
363+
bind("server.undertow.ioThreads", "4");
364+
assertThat(this.properties.getUndertow().getIoThreads()).isEqualTo(4);
365+
// Verify they are locked on same backing props to avoid further downstream
366+
// deprecated testing
367+
assertThat(this.properties.getUndertow().getThreads().getIo()).isEqualTo(4);
368+
}
369+
370+
@Test
371+
void testCustomizeUndertowWorkerThreads() {
372+
bind("server.undertow.threads.worker", "10");
373+
assertThat(this.properties.getUndertow().getThreads().getWorker()).isEqualTo(10);
374+
}
375+
376+
@Deprecated
377+
@Test
378+
void testCustomizeUndertowWorkerThreadsDeprecated() {
379+
bind("server.undertow.workerThreads", "10");
380+
assertThat(this.properties.getUndertow().getWorkerThreads()).isEqualTo(10);
381+
// Verify they are locked on same backing props to avoid further downstream
382+
// deprecated testing
383+
assertThat(this.properties.getUndertow().getThreads().getWorker()).isEqualTo(10);
384+
}
385+
260386
@Test
261387
void testCustomizeJettyAccessLog() {
262388
Map<String, String> map = new HashMap<>();
@@ -295,12 +421,12 @@ void tomcatMaxConnectionsMatchesProtocolDefault() throws Exception {
295421

296422
@Test
297423
void tomcatMaxThreadsMatchesProtocolDefault() throws Exception {
298-
assertThat(this.properties.getTomcat().getMaxThreads()).isEqualTo(getDefaultProtocol().getMaxThreads());
424+
assertThat(this.properties.getTomcat().getThreads().getMax()).isEqualTo(getDefaultProtocol().getMaxThreads());
299425
}
300426

301427
@Test
302428
void tomcatMinSpareThreadsMatchesProtocolDefault() throws Exception {
303-
assertThat(this.properties.getTomcat().getMinSpareThreads())
429+
assertThat(this.properties.getTomcat().getThreads().getMinSpare())
304430
.isEqualTo(getDefaultProtocol().getMinSpareThreads());
305431
}
306432

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,8 @@ void errorReportValveIsConfiguredToNotReportStackTraces() {
345345

346346
@Test
347347
void testCustomizeMinSpareThreads() {
348-
bind("server.tomcat.min-spare-threads=10");
349-
assertThat(this.serverProperties.getTomcat().getMinSpareThreads()).isEqualTo(10);
348+
bind("server.tomcat.threads.min-spare=10");
349+
assertThat(this.serverProperties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
350350
}
351351

352352
@Test

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizerTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,22 @@ void customMaxCookies() {
132132
assertThat(boundServerOption(UndertowOptions.MAX_COOKIES)).isEqualTo(4);
133133
}
134134

135+
@Test
136+
void customizeIoThreads() {
137+
bind("server.undertow.threads.io=4");
138+
ConfigurableUndertowWebServerFactory factory = mock(ConfigurableUndertowWebServerFactory.class);
139+
this.customizer.customize(factory);
140+
verify(factory).setIoThreads(4);
141+
}
142+
143+
@Test
144+
void customizeWorkerThreads() {
145+
bind("server.undertow.threads.worker=10");
146+
ConfigurableUndertowWebServerFactory factory = mock(ConfigurableUndertowWebServerFactory.class);
147+
this.customizer.customize(factory);
148+
verify(factory).setWorkerThreads(10);
149+
}
150+
135151
@Test
136152
void allowEncodedSlashes() {
137153
bind("server.undertow.allow-encoded-slash=true");

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ void customizeServletDisplayName() {
139139
@Test
140140
void testCustomizeTomcatMinSpareThreads() {
141141
Map<String, String> map = new HashMap<>();
142-
map.put("server.tomcat.min-spare-threads", "10");
142+
map.put("server.tomcat.threads.min-spare", "10");
143143
bindProperties(map);
144-
assertThat(this.properties.getTomcat().getMinSpareThreads()).isEqualTo(10);
144+
assertThat(this.properties.getTomcat().getThreads().getMinSpare()).isEqualTo(10);
145145
}
146146

147147
@Test

0 commit comments

Comments
 (0)