diff --git a/docs/src/main/asciidoc/about/doc_overview.adoc b/docs/src/main/asciidoc/about/doc_overview.adoc index b5e737bf344..47ef1fbc7ea 100644 --- a/docs/src/main/asciidoc/about/doc_overview.adoc +++ b/docs/src/main/asciidoc/about/doc_overview.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2018, 2024 Oracle and/or its affiliates. + Copyright (c) 2018, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -112,7 +112,7 @@ xref:{rootdir}/mp/guides/overview.adoc[MP Guides] .Advanced SE Features [icon=hotel_class] -- -xref:{rootdir}/se/webserver.adoc[Helidon WebServer] +xref:{rootdir}/se/webserver/webserver.adoc[Helidon WebServer] xref:{rootdir}/se/metrics/metrics.adoc[Helidon Metrics] diff --git a/docs/src/main/asciidoc/includes/guides/performance-tuning.adoc b/docs/src/main/asciidoc/includes/guides/performance-tuning.adoc index b09dacb9ee4..ca5a903b1fe 100644 --- a/docs/src/main/asciidoc/includes/guides/performance-tuning.adoc +++ b/docs/src/main/asciidoc/includes/guides/performance-tuning.adoc @@ -27,7 +27,7 @@ Still, there might be cases where you wish to change configuration options from For details on the following options please see: -* xref:../../se/webserver.adoc#_configuration_options[WebServer Configuration] +* xref:../../se/webserver/webserver.adoc#_configuration_options[WebServer Configuration] * xref:../../config/io_helidon_common_socket_SocketOptions.adoc[WebServer Socket Configuration] == Summary of Tuning Options diff --git a/docs/src/main/asciidoc/mp/grpc/client.adoc b/docs/src/main/asciidoc/mp/grpc/client.adoc index 258c89a67b7..2cb534898d3 100644 --- a/docs/src/main/asciidoc/mp/grpc/client.adoc +++ b/docs/src/main/asciidoc/mp/grpc/client.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2019, 2024 Oracle and/or its affiliates. + Copyright (c) 2019, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ grpc: TLS in the gRPC MP client section is configured in the same way as in other Helidon components such as the webserver. For more information see -xref:{rootdir}/se/webserver.adoc#_configuring_tls[Configuring TLS]. +xref:{rootdir}/se/webserver/webserver.adoc#_configuring_tls[Configuring TLS]. Given that TLS is enabled by default in gRPC, it must be explicitly turned off by setting the `enabled` flag to `false` when connecting to an unsecure endpoint. diff --git a/docs/src/main/asciidoc/se/cors.adoc b/docs/src/main/asciidoc/se/cors.adoc index 682bbe17ce1..f96f063d0e7 100644 --- a/docs/src/main/asciidoc/se/cors.adoc +++ b/docs/src/main/asciidoc/se/cors.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2022, 2024 Oracle and/or its affiliates. + Copyright (c) 2022, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -139,7 +139,7 @@ The link:{helidon-github-examples-url}/quickstarts/helidon-quickstart-se[Helidon lets you change the greeting by sending a `PUT` request to the `/greet/greeting` resource. This example, based on the QuickStart greeting app, uses the low-level `CrossOriginConfig` API and -the `CorsSupport` API to influence the xref:{rootdir}/se/webserver.adoc#routing[routing], +the `CorsSupport` API to influence the xref:{rootdir}/se/webserver/webserver.adoc#routing[routing], thereby determining how that resource is shared. (If desired, you can use <> instead of the low-level API.) @@ -251,7 +251,7 @@ For a complete example, see {helidon-github-examples-url}/cors[Helidon SE CORS E include::{rootdir}/includes/cors.adoc[tag=cors-and-requested-uri-intro] You can configure how the Helidon server handles these headers as described in the documentation for -xref:{rootdir}/se/webserver.adoc#_requested_uri_discovery[requested URI discovery]. +xref:{rootdir}/se/webserver/webserver.adoc#_requested_uri_discovery[requested URI discovery]. include::{rootdir}/includes/cors.adoc[tag=cors-and-requested-uri-wrapup] diff --git a/docs/src/main/asciidoc/se/guides/upgrade_3x.adoc b/docs/src/main/asciidoc/se/guides/upgrade_3x.adoc index b853362f446..4c1e1b2c9e1 100644 --- a/docs/src/main/asciidoc/se/guides/upgrade_3x.adoc +++ b/docs/src/main/asciidoc/se/guides/upgrade_3x.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2022, 2024 Oracle and/or its affiliates. + Copyright (c) 2022, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ Please follow the instructions in xref:{rootdir}/about/prerequisites.adoc[Prereq Handling routes based on the protocol version is now possible by registering specific routes on routing builder. -For further information check xref:../webserver.adoc[WebServer Documentation] +For further information check xref:../webserver/webserver.adoc[WebServer Documentation] == Http/2 Support @@ -82,7 +82,7 @@ server: max-upgrade-content-length: 16384 ---- -For further information check xref:../webserver.adoc[WebServer Documentation] +For further information check xref:../webserver/webserver.adoc[WebServer Documentation] == WebSocket diff --git a/docs/src/main/asciidoc/se/guides/upgrade_4x.adoc b/docs/src/main/asciidoc/se/guides/upgrade_4x.adoc index a88786aaf65..067684ed328 100644 --- a/docs/src/main/asciidoc/se/guides/upgrade_4x.adoc +++ b/docs/src/main/asciidoc/se/guides/upgrade_4x.adoc @@ -103,7 +103,7 @@ If you want full control using the API, you still have that option. For more information see: * xref:../observability.adoc[Observability feature support] -* xref:../webserver.adoc#_media_types_support[Media types support] +* xref:../webserver/webserver.adoc#_media_types_support[Media types support] == Routing Configuration @@ -176,7 +176,7 @@ It receives `HttpRules` object with routes description. WARNING: These changes make Helidon 4 incompatible with previous versions. -Learn more about `HttpService` and `Routing` at xref:../webserver.adoc[Helidon SE WebServer] +Learn more about `HttpService` and `Routing` at xref:../webserver/webserver.adoc[Helidon SE WebServer] === Other Significant Changes diff --git a/docs/src/main/asciidoc/se/introduction.adoc b/docs/src/main/asciidoc/se/introduction.adoc index 7c6d56baf2d..217a05a16e6 100644 --- a/docs/src/main/asciidoc/se/introduction.adoc +++ b/docs/src/main/asciidoc/se/introduction.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2019, 2024 Oracle and/or its affiliates. + Copyright (c) 2019, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -133,7 +133,7 @@ HTTP client that handles responses to the HTTP requests. //WebServer [CARD] .WebServer -[icon=settings_ethernet,link=webserver.adoc] +[icon=settings_ethernet,link=webserver/webserver.adoc] -- A programmatic HTTP API that uses virtual threads to handle nearly unlimited concurrent requests without blocking a platform thread or starving other requests. // Each request runs in its own dedicated thread, so it is free to perform blocking operations in a simple synchronous way without blocking a platform thread or starving other requests. diff --git a/docs/src/main/asciidoc/se/security/containers-integration.adoc b/docs/src/main/asciidoc/se/security/containers-integration.adoc index b7b66f97371..d1f14ee9065 100644 --- a/docs/src/main/asciidoc/se/security/containers-integration.adoc +++ b/docs/src/main/asciidoc/se/security/containers-integration.adoc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2018, 2024 Oracle and/or its affiliates. + Copyright (c) 2018, 2025 Oracle and/or its affiliates. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ include::{rootdir}/includes/se.adoc[] == WebServer -To integrate xref:../webserver.adoc[web server], add the following dependency to your project's pom.xml file: +To integrate xref:../webserver/webserver.adoc[web server], add the following dependency to your project's pom.xml file: [source,xml] .Maven Dependency diff --git a/docs/src/main/asciidoc/se/webserver/concurrency-limits.adoc b/docs/src/main/asciidoc/se/webserver/concurrency-limits.adoc new file mode 100644 index 00000000000..03a209e6272 --- /dev/null +++ b/docs/src/main/asciidoc/se/webserver/concurrency-limits.adoc @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2025 Oracle and/or its affiliates. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +/////////////////////////////////////////////////////////////////////////////// + += Concurrency Limits +:description: Helidon SE Concurrency Limits +:feature-name: Concurrency Limits +:microprofile-bundle: false +:keywords: helidon, se, performance, concurrency, limits +:rootdir: {docdir}/../.. + +include::{rootdir}/includes/se.adoc[] + +== Introduction + +With the introduction of virtual threads, Helidon is able to create a new +thread per request with the only limit being the available memory on the system. +In some situations, this scenario is not ideal as it can increase concurrency +beyond the capabilities of some other components in the system, such as a database, +a network link, etc. + +In those cases, and when scaling of those components is not feasible or simply not desirable, +it may be beneficial +to limit the number of concurrent requests accepted by the Helidon webserver in +order to improve the overall experience. When doing so, it should also be possible +to establish rules for those requests that cannot be serviced immediately, +as well as how to grow or shrink the number of _permits_ available in the system. + +== Setting Concurrency Limits + +Helidon now includes support for two independent concurrency limit strategies: +fixed and AIMD (Arithmetic Increase Multiplicative Decrease) as well as an SPI +to provide alternative `LimitProvider` implementations. These +concurrency strategies are configured _as a feature_ for each network socket in the +webserver. As always, if configured directly as a webserver feature, it would +apply to the _default_ socket only. + +The following example uses a fixed concurrency strategy to limit the number +of concurrent requests to 1000, a queue of 200 requests to accommodate +potential request bursts and a queue timeout of 1 second: + +[source,yaml] +---- +server: + features: + limits: + concurrency-limit: + fixed: + permits: 1000 + queue-length: 200 + queue-timeout: PT1S +---- + +With this configuration, after all 1000 permits are consumed, subsequent requests +will be queued, if possible, and any request that sits in the queue for more than +1 second will be rejected. + +Instead of fixing the number of permits to a given value, the AIMD strategy +allows the set of permits to grow arithmetically and shrink multiplicatively +as needed, based on the actual time that it takes to process requests. AIMD +can dynamically adjust the number of available permits to ensure a certain +_quality of service_, possibly for a subset of all the requests received. +It is generally preferred to serve a subset of clients efficiently than +all clients inefficiently, and this type of tradeoff can be defined using +an AIMD strategy. For example, + +[source,yaml] +---- +server: + features: + limits: + concurrency-limit: + aimd: + min-limit: 100 + max-limit: 1000 + initial-limit: 500 + timeout: "PT0.5S" + backoff-ratio: 0.75 +---- + +With this configuration, the initial number of permits starts at 500 and +can vary between 100 and 1000. The timeout set at 500 milliseconds is used +to determine how to limit concurrency: if a request completes under this +limit, then the number of permits can increase by one up to the maximum; +if a request fails or if it completes over this limit, then the number +of permits shrinks using the backoff ratio (by 75% in our example) up +to the minimum. + +AIMD also supports queueing and queueing timeouts, so if the maximum size +is reached, it is still possible to accept (enqueue) a request as long +as it is processed within the queueing timeout period. Here is a variation +of the example above, but with a queue of size 300 and a queue timeout of +1 second: + +[source,yaml] +---- +server: + features: + limits: + concurrency-limit: + aimd: + min-limit: 100 + max-limit: 1000 + initial-limit: 500 + timeout: "PT0.5S" + backoff-ratio: 0.75 + queue-length: 300 + queue-timeout: PT1S +---- + +NOTE: Queues can be useful to accommodate short bursts of +requests that would otherwise be rejected when the number of permits +is exhausted. Queueing is disabled by default in both fixed and +AIMD strategies, so `queue-length` must be set to a positive number +to enable this feature. + +Neither of the two strategies shown above enables +queues by default. + +For more information about configuring these Concurrency Limit +strategies see: + +- xref:{rootdir}/config/io_helidon_common_concurrency_limits_FixedLimit.adoc[FixedLimit] +- xref:{rootdir}/config/io_helidon_common_concurrency_limits_AimdLimit.adoc[AimdLimit] + +== Metrics + +The Concurrency Limit module also has built-in support for metrics in order +to monitor the chosen strategy. These metrics are disabled by default, +but can be enabled as follows: + +[source,yaml] +---- +server: + features: + limits: + concurrency-limit: + fixed: + permits: 1000 + queue-length: 200 + queue-timeout: PT1S + enable-metrics: true # turn on metrics! +---- + +The following tables describe the metrics that are available for each of the +strategies described above. A metric tag `socketName=` is used to +group metrics that correspond to a particular socket; for simplicity this metric tag +is _omitted_ for the default socket. All metrics provided by the Concurrency Limit +module are in **vendor** scope. + +.Fixed +|=== +|Name |Description + +|`fixed_queue_length` +|Gauge that returns the number of requests waiting on the queue at a certain time + +|`fixed_rejected_requests` +|Gauge that returns the number of requests that have been rejected so far + +|`fixed_rtt` +|Distribution summary of round-trip times, excluding any time waiting in the queue + +|`fixed_queue_wait_time` +|Distribution summary of queue wait times + +|`fixed_concurrent_requests` +|Gauge that returns the number of requests being processed at a certain time +|=== + +.AIMD +|=== +|Name |Description + +|`aimd_queue_length` +|Gauge that returns the number of requests waiting on the queue at a certain time + +|`aimd_rejected_requests` +|Gauge that returns the number of requests that have been rejected so far + +|`aimd_rtt` +|Distribution summary of round-trip times, excluding any time waiting in the queue + +|`aimd_queue_wait_time` +|Distribution summary of queue wait times + +|`aimd_concurrent_requests` +|Gauge that returns the number of requests being processed at a certain time + +|`aimd_limit` +|Gauge that returns the actual limit at a certain time +|=== + +For more information regarding metrics support in Helidon and the dependencies that are +required for metrics to work, see xref:{metrics-page}[Helidon Metrics]. diff --git a/docs/src/main/asciidoc/se/webserver.adoc b/docs/src/main/asciidoc/se/webserver/webserver.adoc similarity index 99% rename from docs/src/main/asciidoc/se/webserver.adoc rename to docs/src/main/asciidoc/se/webserver/webserver.adoc index a852443ac86..acecbb57004 100644 --- a/docs/src/main/asciidoc/se/webserver.adoc +++ b/docs/src/main/asciidoc/se/webserver/webserver.adoc @@ -20,7 +20,7 @@ :description: Helidon WebServer Introduction :keywords: helidon, java, webserver, tls :feature-name: WebServer -:rootdir: {docdir}/.. +:rootdir: {docdir}/../.. :requested-uri-discovery-inc: {rootdir}/includes/server/requested-uri-discovery.adoc include::{rootdir}/includes/se.adoc[] @@ -526,22 +526,22 @@ first. |<> |1000 -|xref:tracing.adoc[Tracing] +|xref:{rootdir}/se/tracing.adoc[Tracing] |900 -|xref:cors.adoc[CORS] +|xref:{rootdir}/se/cors.adoc[CORS] |850 -|xref:security/introduction.adoc[Security] +|xref:{rootdir}/se/security/introduction.adoc[Security] |800 |Routing (all handlers and filters) |100 -|xref:openapi/openapi.adoc[OpenAPI] +|xref:{rootdir}/se/openapi/openapi.adoc[OpenAPI] |90 -|xref:observability.adoc[Observability] +|xref:{rootdir}/se/observability.adoc[Observability] |80 |=== diff --git a/docs/src/main/asciidoc/sitegen.yaml b/docs/src/main/asciidoc/sitegen.yaml index 0bb814939e4..89cd3a0dc21 100644 --- a/docs/src/main/asciidoc/sitegen.yaml +++ b/docs/src/main/asciidoc/sitegen.yaml @@ -441,12 +441,15 @@ backend: sources: - "engine.adoc" - "rsoperators.adoc" - - type: "PAGE" + - type: "MENU" title: "Webserver" - source: "webserver.adoc" + dir: "webserver" glyph: type: "icon" value: "settings_ethernet" + sources: + - "webserver.adoc" + - "concurrency-limits.adoc" - type: "PAGE" title: "Scheduling" source: "scheduling.adoc"