From 6cb5d7dbd5238578f5d5b7b27e1f98e2715b36d2 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Tue, 10 Sep 2024 15:07:55 -0500 Subject: [PATCH] fix: Added additional jetty configuration options (#6043) Deployments can now specify max h2 streams per connection and max request header size. Set the configuration property `http2.maxConcurrentStreams` to the number of streams to allow for a given h2 connection. Set the configuration property `http.maxHeaderRequestSize` to the max number of bytes to allow in HTTP request headers. Fixes #5934 Fixes #6021 --- .../server/jetty/JettyBackedGrpcServer.java | 4 +++ .../deephaven/server/jetty/JettyConfig.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/server/jetty/src/main/java/io/deephaven/server/jetty/JettyBackedGrpcServer.java b/server/jetty/src/main/java/io/deephaven/server/jetty/JettyBackedGrpcServer.java index 6122b287bcc..641948d9489 100644 --- a/server/jetty/src/main/java/io/deephaven/server/jetty/JettyBackedGrpcServer.java +++ b/server/jetty/src/main/java/io/deephaven/server/jetty/JettyBackedGrpcServer.java @@ -325,6 +325,7 @@ private static ServerConnector createConnector(Server server, JettyConfig config httpConfig.addCustomizer(new SecureRequestCustomizer(config.sniHostCheck())); final HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpConfig); h2.setRateControlFactory(new RateControl.Factory() {}); + config.maxConcurrentStreams().ifPresent(h2::setMaxConcurrentStreams); final ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); alpn.setDefaultProtocol(http11 != null ? http11.getProtocol() : h2.getProtocol()); @@ -345,6 +346,8 @@ private static ServerConnector createConnector(Server server, JettyConfig config } else { final HTTP2CServerConnectionFactory h2c = new HTTP2CServerConnectionFactory(httpConfig); h2c.setRateControlFactory(new RateControl.Factory() {}); + config.maxConcurrentStreams().ifPresent(h2c::setMaxConcurrentStreams); + if (http11 != null) { serverConnector = new ServerConnector(server, http11, h2c); } else { @@ -353,6 +356,7 @@ private static ServerConnector createConnector(Server server, JettyConfig config } config.host().ifPresent(serverConnector::setHost); serverConnector.setPort(config.port()); + config.maxHeaderRequestSize().ifPresent(httpConfig::setRequestHeaderSize); // Give connections extra time to shutdown, since we have an explicit server shutdown serverConnector.setShutdownIdleTimeout(serverConnector.getIdleTimeout()); diff --git a/server/jetty/src/main/java/io/deephaven/server/jetty/JettyConfig.java b/server/jetty/src/main/java/io/deephaven/server/jetty/JettyConfig.java index 109cd2371d3..5dc058c8e16 100644 --- a/server/jetty/src/main/java/io/deephaven/server/jetty/JettyConfig.java +++ b/server/jetty/src/main/java/io/deephaven/server/jetty/JettyConfig.java @@ -11,6 +11,8 @@ import org.immutables.value.Value.Style; import javax.annotation.Nullable; +import java.util.Optional; +import java.util.OptionalInt; import java.util.OptionalLong; /** @@ -29,6 +31,8 @@ public abstract class JettyConfig implements ServerConfig { public static final String HTTP_STREAM_TIMEOUT = "http2.stream.idleTimeoutMs"; public static final String HTTP_COMPRESSION = "http.compression"; public static final String SNI_HOST_CHECK = "https.sniHostCheck"; + public static final String MAX_CONCURRENT_STREAMS = "http2.maxConcurrentStreams"; + public static final String MAX_HEADER_REQUEST_SIZE = "http.maxHeaderRequestSize"; /** * Values to indicate what kind of websocket support should be offered. @@ -93,6 +97,8 @@ public static Builder buildFromConfig(Configuration config) { String httpCompression = config.getStringWithDefault(HTTP_COMPRESSION, null); String sniHostCheck = config.getStringWithDefault(SNI_HOST_CHECK, null); String h2StreamIdleTimeout = config.getStringWithDefault(HTTP_STREAM_TIMEOUT, null); + String h2MaxConcurrentStreams = config.getStringWithDefault(MAX_CONCURRENT_STREAMS, null); + String maxHeaderRequestSize = config.getStringWithDefault(MAX_HEADER_REQUEST_SIZE, null); if (httpWebsockets != null) { switch (httpWebsockets.toLowerCase()) { case "true":// backwards compatible @@ -122,6 +128,12 @@ public static Builder buildFromConfig(Configuration config) { if (sniHostCheck != null) { builder.sniHostCheck(Boolean.parseBoolean(sniHostCheck)); } + if (h2MaxConcurrentStreams != null) { + builder.maxConcurrentStreams(Integer.parseInt(h2MaxConcurrentStreams)); + } + if (maxHeaderRequestSize != null) { + builder.maxHeaderRequestSize(Integer.parseInt(maxHeaderRequestSize)); + } return builder; } @@ -212,6 +224,16 @@ public final boolean httpCompressionOrDefault() { return httpCompression == null || httpCompression; } + /** + * Value is in bytes. If unset, uses Jetty's default (presently 8192). + */ + public abstract OptionalInt maxHeaderRequestSize(); + + /** + * If unset, uses Jetty's default (presently 128). Only applies to http2 connections. + */ + public abstract OptionalInt maxConcurrentStreams(); + public interface Builder extends ServerConfig.Builder { Builder websockets(WebsocketsSupport websockets); @@ -223,5 +245,9 @@ public interface Builder extends ServerConfig.Builder { Builder http2StreamIdleTimeout(long timeoutInMillis); Builder sniHostCheck(boolean sniHostCheck); + + Builder maxHeaderRequestSize(int maxHeaderRequestSize); + + Builder maxConcurrentStreams(int maxConcurrentStreams); } }