Skip to content

Commit 3e4a9f5

Browse files
committed
Add property to limit maximum connections for Jetty
Closes gh-35899
1 parent f81787e commit 3e4a9f5

7 files changed

Lines changed: 73 additions & 0 deletions

File tree

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,12 @@ public static class Jetty {
11231123
*/
11241124
private DataSize maxHttpResponseHeaderSize = DataSize.ofKilobytes(8);
11251125

1126+
/**
1127+
* Maximum number of connections that the server accepts and processes at any
1128+
* given time.
1129+
*/
1130+
private int maxConnections = -1;
1131+
11261132
public Accesslog getAccesslog() {
11271133
return this.accesslog;
11281134
}
@@ -1155,6 +1161,14 @@ public void setMaxHttpResponseHeaderSize(DataSize maxHttpResponseHeaderSize) {
11551161
this.maxHttpResponseHeaderSize = maxHttpResponseHeaderSize;
11561162
}
11571163

1164+
public int getMaxConnections() {
1165+
return this.maxConnections;
1166+
}
1167+
1168+
public void setMaxConnections(int maxConnections) {
1169+
this.maxConnections = maxConnections;
1170+
}
1171+
11581172
/**
11591173
* Jetty access log properties.
11601174
*/

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void customize(ConfigurableJettyWebServerFactory factory) {
8181
ServerProperties.Jetty.Threads threadProperties = properties.getThreads();
8282
factory.setThreadPool(determineThreadPool(properties.getThreads()));
8383
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
84+
map.from(properties::getMaxConnections).to(factory::setMaxConnections);
8485
map.from(threadProperties::getAcceptors).to(factory::setAcceptors);
8586
map.from(threadProperties::getSelectors).to(factory::setSelectors);
8687
map.from(this.serverProperties::getMaxHttpRequestHeaderSize)

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/ConfigurableJettyWebServerFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* {@link ConfigurableWebServerFactory} for Jetty-specific features.
2626
*
2727
* @author Brian Clozel
28+
* @author Moritz Halbritter
2829
* @since 2.0.0
2930
* @see JettyServletWebServerFactory
3031
* @see JettyReactiveWebServerFactory
@@ -63,4 +64,11 @@ public interface ConfigurableJettyWebServerFactory extends ConfigurableWebServer
6364
*/
6465
void addServerCustomizers(JettyServerCustomizer... customizers);
6566

67+
/**
68+
* Sets the maximum number of concurrent connections.
69+
* @param maxConnections the maximum number of concurrent connections
70+
* @since 3.2.0
71+
*/
72+
void setMaxConnections(int maxConnections);
73+
6674
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
3030
import org.eclipse.jetty.server.AbstractConnector;
3131
import org.eclipse.jetty.server.ConnectionFactory;
32+
import org.eclipse.jetty.server.ConnectionLimit;
3233
import org.eclipse.jetty.server.Handler;
3334
import org.eclipse.jetty.server.HttpConfiguration;
3435
import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -55,6 +56,7 @@
5556
* {@link ReactiveWebServerFactory} that can be used to create {@link JettyWebServer}s.
5657
*
5758
* @author Brian Clozel
59+
* @author Moritz Halbritter
5860
* @since 2.0.0
5961
*/
6062
public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory
@@ -80,6 +82,8 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
8082

8183
private ThreadPool threadPool;
8284

85+
private int maxConnections = -1;
86+
8387
/**
8488
* Create a new {@link JettyServletWebServerFactory} instance.
8589
*/
@@ -118,6 +122,11 @@ public void addServerCustomizers(JettyServerCustomizer... customizers) {
118122
this.jettyServerCustomizers.addAll(Arrays.asList(customizers));
119123
}
120124

125+
@Override
126+
public void setMaxConnections(int maxConnections) {
127+
this.maxConnections = maxConnections;
128+
}
129+
121130
/**
122131
* Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server}
123132
* before it is started. Calling this method will replace any existing customizers.
@@ -180,6 +189,9 @@ protected Server createJettyServer(JettyHttpHandlerAdapter servlet) {
180189
contextHandler.addServlet(servletHolder, "/");
181190
server.setHandler(addHandlerWrappers(contextHandler));
182191
JettyReactiveWebServerFactory.logger.info("Server initialized with port: " + port);
192+
if (this.maxConnections > -1) {
193+
server.addBean(new ConnectionLimit(this.maxConnections, server));
194+
}
183195
if (Ssl.isEnabled(getSsl())) {
184196
customizeSsl(server, address);
185197
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
4444
import org.eclipse.jetty.server.AbstractConnector;
4545
import org.eclipse.jetty.server.ConnectionFactory;
46+
import org.eclipse.jetty.server.ConnectionLimit;
4647
import org.eclipse.jetty.server.Connector;
4748
import org.eclipse.jetty.server.Handler;
4849
import org.eclipse.jetty.server.HttpConfiguration;
@@ -101,6 +102,7 @@
101102
* @author Eddú Meléndez
102103
* @author Venil Noronha
103104
* @author Henri Kerola
105+
* @author Moritz Halbritter
104106
* @since 2.0.0
105107
* @see #setPort(int)
106108
* @see #setConfigurations(Collection)
@@ -129,6 +131,8 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
129131

130132
private ThreadPool threadPool;
131133

134+
private int maxConnections = -1;
135+
132136
/**
133137
* Create a new {@link JettyServletWebServerFactory} instance.
134138
*/
@@ -163,6 +167,9 @@ public WebServer getWebServer(ServletContextInitializer... initializers) {
163167
configureWebAppContext(context, initializers);
164168
server.setHandler(addHandlerWrappers(context));
165169
this.logger.info("Server initialized with port: " + port);
170+
if (this.maxConnections > -1) {
171+
server.addBean(new ConnectionLimit(this.maxConnections, server));
172+
}
166173
if (Ssl.isEnabled(getSsl())) {
167174
customizeSsl(server, address);
168175
}
@@ -458,6 +465,11 @@ public void setSelectors(int selectors) {
458465
this.selectors = selectors;
459466
}
460467

468+
@Override
469+
public void setMaxConnections(int maxConnections) {
470+
this.maxConnections = maxConnections;
471+
}
472+
461473
/**
462474
* Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server}
463475
* before it is started. Calling this method will replace any existing customizers.

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Arrays;
2323

2424
import org.awaitility.Awaitility;
25+
import org.eclipse.jetty.server.ConnectionLimit;
2526
import org.eclipse.jetty.server.Connector;
2627
import org.eclipse.jetty.server.Server;
2728
import org.eclipse.jetty.server.ServerConnector;
@@ -47,6 +48,7 @@
4748
*
4849
* @author Brian Clozel
4950
* @author Madhura Bhave
51+
* @author Moritz Halbritter
5052
*/
5153
@Servlet5ClassPathOverrides
5254
class JettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactoryTests {
@@ -148,4 +150,15 @@ void whenServerIsShuttingDownGracefullyThenNewConnectionsCannotBeMade() {
148150
this.webServer.stop();
149151
}
150152

153+
@Test
154+
void shouldApplyMaxConnections() {
155+
JettyReactiveWebServerFactory factory = getFactory();
156+
factory.setMaxConnections(1);
157+
this.webServer = factory.getWebServer(new EchoHandler());
158+
Server server = ((JettyWebServer) this.webServer).getServer();
159+
ConnectionLimit connectionLimit = server.getBean(ConnectionLimit.class);
160+
assertThat(connectionLimit).isNotNull();
161+
assertThat(connectionLimit.getMaxConnections()).isOne();
162+
}
163+
151164
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.hc.core5.http.HttpResponse;
4141
import org.apache.jasper.servlet.JspServlet;
4242
import org.awaitility.Awaitility;
43+
import org.eclipse.jetty.server.ConnectionLimit;
4344
import org.eclipse.jetty.server.Connector;
4445
import org.eclipse.jetty.server.Handler;
4546
import org.eclipse.jetty.server.Server;
@@ -86,6 +87,7 @@
8687
* @author Dave Syer
8788
* @author Andy Wilkinson
8889
* @author Henri Kerola
90+
* @author Moritz Halbritter
8991
*/
9092
@Servlet5ClassPathOverrides
9193
class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryTests {
@@ -518,6 +520,17 @@ public void configure(WebAppContext context) throws Exception {
518520
assertThat(context.getErrorHandler()).isInstanceOf(CustomErrorHandler.class);
519521
}
520522

523+
@Test
524+
void shouldApplyMaxConnections() {
525+
JettyServletWebServerFactory factory = getFactory();
526+
factory.setMaxConnections(1);
527+
this.webServer = factory.getWebServer();
528+
Server server = ((JettyWebServer) this.webServer).getServer();
529+
ConnectionLimit connectionLimit = server.getBean(ConnectionLimit.class);
530+
assertThat(connectionLimit).isNotNull();
531+
assertThat(connectionLimit.getMaxConnections()).isOne();
532+
}
533+
521534
private WebAppContext findWebAppContext(JettyWebServer webServer) {
522535
return findWebAppContext(webServer.getServer().getHandler());
523536
}

0 commit comments

Comments
 (0)