From a325017098210a6bc9c520908fe5579de99026e9 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Mon, 25 Sep 2023 12:00:02 +0200 Subject: [PATCH] Add support for traffic shaping --- docs/src/main/asciidoc/http-reference.adoc | 41 ++++++++++ .../vertx/http/runtime/HttpConfiguration.java | 4 +- .../http/runtime/TrafficShapingConfig.java | 77 +++++++++++++++++++ .../options/HttpServerOptionsUtils.java | 30 ++++++++ 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/TrafficShapingConfig.java diff --git a/docs/src/main/asciidoc/http-reference.adoc b/docs/src/main/asciidoc/http-reference.adoc index b263355b218102..18acad7844d684 100644 --- a/docs/src/main/asciidoc/http-reference.adoc +++ b/docs/src/main/asciidoc/http-reference.adoc @@ -394,6 +394,47 @@ It is important that you enable all origins only for the dev profile, allowing a include::{generated-dir}/config/quarkus-vertx-http-config-group-server-limits-config.adoc[leveloffset=+1, opts=optional] +== Configure traffic shaping + +Traffic shaping allows you to limit the bandwidth across all channels (i.e. connections), regardless of the number of open channels. +This can be useful when you want to control the overall network traffic to prevent congestion or prioritize certain types of traffic. + +To enable traffic shaping, add the following property in your application configuration: + + +[source, properties] +---- +quarkus.http.traffic-shaping.enabled=true # Required to enable traffic shaping +---- + +The traffic shaping allows you to configure various parameters, such as write and read limitations (in bytes per second), check interval (the delay between two computations of the bandwidth), and maximum time to wait: + +[source, properties] +---- +quarkus.http.traffic-shaping.enabled=true # Required to enable traffic shaping +quarkus.http.traffic-shaping.check-interval=30s +quarkus.http.traffic-shaping.outbound-global-bandwidth=1M +quarkus.http.traffic-shaping.inbound-global-bandwidth=1M +quarkus.http.traffic-shaping.max-delay=10s +---- + +The check interval represents the period at which the traffic is computed, and a higher interval may result in + less precise traffic shaping. +Despite 0 is accepted (no accounting), it is recommended to set a positive value for the check interval, even if it is high since the precision of the traffic shaping depends on the period where the traffic is computed. +In this case, a suggested value is something close to 5 or 10 minutes. + + The `outbound-global-bandwidth` and `inbound-global-bandwidth` parameters represent the maximum number of bytes per second for write and read operations, respectively. +You shall also consider to have object size in read or write operations relatively adapted to the bandwidth you required. +For instance having 10 MB objects for 10KB/s will lead to burst effect, while having 100 KB objects for 1 MB/s should be smoothly handle by the traffic shaping. + +Additionally, you can set the maximum time to wait (`max-delay`), which specifies an upper bound for time shaping. +By default, it is set to 15 seconds. +It must be less than the HTTP timeout. +When one of the threshold is reached, no write happens for that period of time. + +include::{generated-dir}/config/quarkus-vertx-http-config-group-traffic-shaping-config.adoc[leveloffset=+1, opts=optional] + + == Configuring HTTP Access Logs You can add HTTP request logging by configuring it in `application.properties`. There are two options for logging, diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java index c301b99754848f..89ffdf53d0c198 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java @@ -229,7 +229,9 @@ public class HttpConfiguration { @ConfigItem public boolean recordRequestStartTime; - AccessLogConfig accessLog; + public AccessLogConfig accessLog; + + public TrafficShapingConfig trafficShaping; /** * Configuration that allows setting the same site attributes for cookies. diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/TrafficShapingConfig.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/TrafficShapingConfig.java new file mode 100644 index 00000000000000..b9a0f8c4b80b90 --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/TrafficShapingConfig.java @@ -0,0 +1,77 @@ +package io.quarkus.vertx.http.runtime; + +import java.time.Duration; +import java.util.Optional; + +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; +import io.quarkus.runtime.configuration.MemorySize; + +/** + * Configure the global traffic shaping functionality. + * It allows you to limit the bandwidth across all channels, regardless of the number of open channels. + * This can be useful when you want to control the overall network traffic to prevent congestion + * or prioritize certain types of traffic. + *

+ * The traffic shaping allows you to configure various parameters, such as write and read limitations (in bytes per + * second), check interval (the delay between two computations of the bandwidth), and maximum time to wait. + * The check interval represents the period at which the traffic is computed, and a higher interval may result in + * less precise traffic shaping. It is recommended to set a positive value for the check interval, even if it is high, + * to ensure traffic shaping without accounting. A suggested value is something close to 5 or 10 minutes. + *

+ * The `outbound-global-bandwidth` and `inbound-global-bandwidth` parameters represent the maximum number of bytes per second + * for write and read operations, respectively. + * Additionally, you can set the maximum time to wait, which specifies an upper bound for time shaping. + * By default, it is set to 15 seconds. + */ +@ConfigGroup +public class TrafficShapingConfig { + + /** + * Enables the traffic shaping. + */ + @ConfigItem(defaultValue = "false") + public boolean enabled; + + /** + * Set bandwidth limit in bytes per second for inbound connections. + * If not set, no limits are applied. + */ + @ConfigItem + public Optional inboundGlobalBandwidth; + + /** + * Set bandwidth limit in bytes per second for outbound connections. + * If not set, no limits are applied. + */ + @ConfigItem + public Optional outboundGlobalBandwidth; + + /** + * Set the maximum delay to wait in case of traffic excess. + * Default is 15s. Must be less than the HTTP timeout. + */ + @ConfigItem + public Optional maxDelay; + + /** + * Set the delay between two computations of performances for channels. + * If set to 0, no stats are computed. + * Despite 0 is accepted (no accounting), it is recommended to set a positive value for the check interval, + * even if it is high since the precision of the traffic shaping depends on the period where the traffic is computed. + * In this case, a suggested value is something close to 5 or 10 minutes. + *

+ * If not default, it defaults to 1s. + */ + @ConfigItem + public Optional checkInterval; + + /** + * Set the maximum global write size in bytes per second allowed in the buffer globally for all channels before write + * are suspended. + * The default value is 400 MB. + */ + @ConfigItem + public Optional peakOutboundGlobalBandwidth; + +} diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java index bd20ba9b5c813c..20e9fa1eb61939 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java @@ -29,7 +29,9 @@ import io.vertx.core.net.JdkSSLEngineOptions; import io.vertx.core.net.KeyStoreOptions; import io.vertx.core.net.PemKeyCertOptions; +import io.vertx.core.net.TrafficShapingOptions; +@SuppressWarnings("OptionalIsPresent") public class HttpServerOptionsUtils { /** @@ -276,6 +278,34 @@ public static void applyCommonOptions(HttpServerOptions httpServerOptions, } httpServerOptions.setUseProxyProtocol(httpConfiguration.proxy.useProxyProtocol); + configureTrafficShapingIfEnabled(httpServerOptions, httpConfiguration); + } + + private static void configureTrafficShapingIfEnabled(HttpServerOptions httpServerOptions, + HttpConfiguration httpConfiguration) { + if (httpConfiguration.trafficShaping.enabled) { + TrafficShapingOptions options = new TrafficShapingOptions(); + if (httpConfiguration.trafficShaping.checkInterval.isPresent()) { + options.setCheckIntervalForStats(httpConfiguration.trafficShaping.checkInterval.get().toSeconds()); + options.setCheckIntervalForStatsTimeUnit(TimeUnit.SECONDS); + } + if (httpConfiguration.trafficShaping.maxDelay.isPresent()) { + options.setMaxDelayToWait(httpConfiguration.trafficShaping.maxDelay.get().toSeconds()); + options.setMaxDelayToWaitUnit(TimeUnit.SECONDS); + } + if (httpConfiguration.trafficShaping.inboundGlobalBandwidth.isPresent()) { + options.setInboundGlobalBandwidth(httpConfiguration.trafficShaping.inboundGlobalBandwidth.get().asLongValue()); + } + if (httpConfiguration.trafficShaping.outboundGlobalBandwidth.isPresent()) { + options.setOutboundGlobalBandwidth( + httpConfiguration.trafficShaping.outboundGlobalBandwidth.get().asLongValue()); + } + if (httpConfiguration.trafficShaping.peakOutboundGlobalBandwidth.isPresent()) { + options.setPeakOutboundGlobalBandwidth( + httpConfiguration.trafficShaping.peakOutboundGlobalBandwidth.get().asLongValue()); + } + httpServerOptions.setTrafficShapingOptions(options); + } } public static void applyCommonOptionsForManagementInterface(HttpServerOptions options,