This is an automated email from the ASF dual-hosted git repository. robertlazarski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git
commit df812ef92d9ee42bc68e8d33e0090e74569595cf Author: Robert Lazarski <[email protected]> AuthorDate: Mon May 4 09:29:16 2026 -1000 AXIS2-6103 Correct HTTP/2 initialWindowSize guidance in transport docs The docs recommended setting the client-side initialWindowSize to 65536 (64KB) to "align" with the server-side FlushingOutputStream 64KB flush interval. These are independent settings: the flush interval controls when serialized bytes enter the HTTP/2 framing layer (server-side, 64KB is correct), while initialWindowSize controls how much response data can be in-flight per stream before the sender pauses for a WINDOW_UPDATE (client-side, 64KB causes ~156 round-trips for a 10MB response). Changes: - Raise default initialWindowSize from 65536 to 2097152 (2MB) in basic config and parameter table - Add callout box explaining flush interval vs flow-control window - Add "Tuning for Different Workloads" section with guidance for many-small, few-large, and mixed traffic patterns - Add "Client-side vs server-side window" subsection explaining why client-side tuning matters more for large-response workloads - Fix Enterprise Big Data config: maxConcurrentStreams 50->4, initialWindowSize 128KB->8MB, maxConnPerRoute 10->32 - Update WildFly guide with correction note on window alignment - Fix simplified example initialWindowSize from 65536 to 2097152 --- .../xdoc/docs/axis2-http2-simplified-example.xml | 4 +- src/site/xdoc/docs/http2-transport-additions.xml | 95 +++++++++++++++++++--- .../xdoc/docs/wildfly-http2-integration-guide.xml | 20 ++++- 3 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/site/xdoc/docs/axis2-http2-simplified-example.xml b/src/site/xdoc/docs/axis2-http2-simplified-example.xml index 091de2921c..ed3c030f23 100644 --- a/src/site/xdoc/docs/axis2-http2-simplified-example.xml +++ b/src/site/xdoc/docs/axis2-http2-simplified-example.xml @@ -124,8 +124,8 @@ maxConcurrentStreams = 100 # Memory-constrained optimization maxConnectionsTotal = 50 # Enterprise connection management maxConnectionsPerRoute = 10 # Route-specific optimization -initialWindowSize = 65536 # 64KB large payload optimization -streamingBufferSize = 65536 # Aligned buffer processing +initialWindowSize = 2097152 # 2MB flow-control window (not related to 64KB flush interval) +streamingBufferSize = 65536 # Server-side flush interval (64KB is correct here) connectionKeepAliveTime = 300000 # 5-minute balanced timeout connectionTimeout = 30000 # 30-second connection establishment responseTimeout = 300000 # 5-minute large payload tolerance diff --git a/src/site/xdoc/docs/http2-transport-additions.xml b/src/site/xdoc/docs/http2-transport-additions.xml index 3ad0fd8bca..5b4a11670b 100644 --- a/src/site/xdoc/docs/http2-transport-additions.xml +++ b/src/site/xdoc/docs/http2-transport-additions.xml @@ -110,34 +110,109 @@ within enterprise memory constraints (2GB heap).</p> <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> <parameter name="maxConcurrentStreams">100</parameter> - <parameter name="initialWindowSize">65536</parameter> + <parameter name="initialWindowSize">2097152</parameter> <!-- 2MB -- see note below --> <parameter name="serverPushEnabled">false</parameter> <parameter name="memoryOptimized">true</parameter> </transportSender> </pre> +<div style="background-color: #fff8e1; border: 1px solid #f9a825; padding: 15px; margin: 15px 0;"> +<h4>Flow-control window vs. streaming flush interval</h4> +<p><code>initialWindowSize</code> and the <code>FlushingOutputStream</code> +64 KB flush interval are <strong>independent settings that should not be +"aligned"</strong> to the same value.</p> +<ul> + <li><strong>FlushingOutputStream flush (server-side, 64 KB)</strong> — + controls when serialized bytes are pushed into the HTTP/2 framing + layer. 64 KB is a good cadence: it gives early time-to-first-byte + and prevents reverse proxy timeouts on long-running serializations. + This value is correct and should not change.</li> + <li><strong>initialWindowSize (client-side, per-stream)</strong> — + controls how much data a stream may have in-flight before the + sender pauses for a WINDOW_UPDATE acknowledgement from the + receiver. A 10 MB response with a 64 KB window requires ~156 + WINDOW_UPDATE round-trips; with a 2 MB window it requires ~5. + Under concurrent load, these round-trips serialize on each TCP + connection, adding significant latency.</li> +</ul> +<p>A server flushing at 64 KB works well with a client whose +window is 2 MB — the server sends 64 KB, the framing layer +accumulates up to 2 MB of in-flight data, and the client +acknowledges in bulk. Setting both to 64 KB forces the client to +acknowledge every single flush, converting each 64 KB chunk into a +synchronous round-trip.</p> +</div> + <h3>HTTP/2 Configuration Parameters</h3> <table border="1"> <tr><th>Parameter</th><th>Description</th><th>Default</th><th>Range</th></tr> -<tr><td>maxConcurrentStreams</td><td>Maximum concurrent streams per connection</td><td>100</td><td>1-1000</td></tr> -<tr><td>initialWindowSize</td><td>Initial flow control window size (bytes)</td><td>65536</td><td>32KB-16MB</td></tr> +<tr><td>maxConcurrentStreams</td><td>Maximum concurrent streams per connection. Lower values (4-8) force the connection pool to spread streams across multiple TCP connections — better for workloads with few concurrent large payloads. Higher values (50-100) maximize multiplexing efficiency for many small concurrent requests.</td><td>100</td><td>1-1000</td></tr> +<tr><td>initialWindowSize</td><td>HTTP/2 per-stream flow-control window (bytes). Determines how much data can be in-flight per stream before the sender waits for a WINDOW_UPDATE. For payloads above 1 MB, use at least 1-2 MB to avoid excessive round-trips. Not related to the server-side FlushingOutputStream 64 KB flush interval.</td><td>2097152</td><td>64KB-16MB</td></tr> <tr><td>serverPushEnabled</td><td>Enable HTTP/2 server push</td><td>false</td><td>true/false</td></tr> <tr><td>memoryOptimized</td><td>Enable adaptive memory management</td><td>true</td><td>true/false</td></tr> <tr><td>largePayloadThreshold</td><td>Threshold for large payload optimization</td><td>52428800</td><td>10MB-500MB</td></tr> <tr><td>compressionEnabled</td><td>Enable intelligent compression</td><td>true</td><td>true/false</td></tr> </table> +<h3>Tuning for Different Workloads</h3> + +<p>The optimal <code>maxConcurrentStreams</code> and +<code>initialWindowSize</code> depend on your traffic pattern. With +Apache HttpComponents 5.x, the <code>PoolingAsyncClientConnectionManager</code> +only opens a new TCP connection when all existing connections have reached +their <code>maxConcurrentStreams</code> limit. If this value is higher +than your typical concurrency, the pool will multiplex all streams onto a +single connection — which is efficient for many small requests but creates +flow-control contention for concurrent large payloads.</p> + +<table border="1"> +<tr><th>Workload</th><th>Example</th><th>maxConcurrentStreams</th><th>initialWindowSize</th><th>maxConnPerRoute</th></tr> +<tr><td>Many small concurrent requests</td><td>Microservice mesh, API gateway</td><td>50-100</td><td>2 MB</td><td>10</td></tr> +<tr><td>Few large concurrent payloads</td><td>Batch processing, ETL, report generation</td><td>4-8</td><td>8 MB</td><td>16-32</td></tr> +<tr><td>Mixed traffic</td><td>General-purpose service client</td><td>8-16</td><td>2 MB</td><td>16</td></tr> +</table> + +<h4>Client-side vs. server-side window: where tuning matters</h4> + +<p>HTTP/2 flow control is bidirectional — both client and server +advertise an <code>initialWindowSize</code>. For typical Axis2 +deployments where the server produces large JSON responses and the +client sends smaller requests (query parameters, filter criteria), +the <strong>client-side window is the critical tuning point</strong>. +It governs how much response data the server can push before pausing +for a WINDOW_UPDATE from the client. A 64 KB client window on a +10 MB response means ~156 pause-and-acknowledge cycles.</p> + +<p>The server's inbound window (configured in the application server — +e.g., WildFly's <code>http2-initial-window-size</code>, Tomcat's +<code>http2InitialWindowSize</code>) controls how much +<em>request</em> data the server allows in-flight. Since requests +are typically small relative to responses, the server-side default +(64 KB per the HTTP/2 spec) is usually adequate. Focus tuning effort +on the <code>H2TransportSender</code> client-side +<code>initialWindowSize</code> shown above.</p> + +<p>If a single client consumes both small and large payload endpoints on +different hosts, consider configuring separate +<code>CloseableHttpAsyncClient</code> instances with per-workload tuning. +The connection pool's <code>maxConnPerRoute</code> already isolates +traffic by host, but <code>maxConcurrentStreams</code> and +<code>initialWindowSize</code> apply to the entire client.</p> + <h3>Enterprise Big Data Configuration</h3> -<p>For enterprise applications processing large JSON datasets (50MB+), use the following optimized configuration:</p> +<p>For enterprise applications processing large JSON datasets (50MB+), use the following optimized configuration. +Note the lower <code>maxConcurrentStreams</code> (forces the pool to open multiple TCP connections under concurrent +load) and larger <code>initialWindowSize</code> (eliminates per-stream flow-control round-trips):</p> <pre> <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> <parameter name="PROTOCOL">HTTP/2.0</parameter> - <!-- Stream Management --> - <parameter name="maxConcurrentStreams">50</parameter> - <parameter name="initialWindowSize">131072</parameter> + <!-- Stream Management: low stream count forces connection pooling + instead of multiplexing all large payloads onto one TCP connection --> + <parameter name="maxConcurrentStreams">4</parameter> + <parameter name="initialWindowSize">8388608</parameter> <!-- 8MB -- a 50MB payload completes in ~6 window updates --> <parameter name="maxFrameSize">32768</parameter> <!-- Large Payload Optimization --> @@ -150,9 +225,9 @@ within enterprise memory constraints (2GB heap).</p> <parameter name="adaptiveFlowControl">true</parameter> <parameter name="bufferPooling">true</parameter> - <!-- Connection Management --> - <parameter name="maxConnTotal">50</parameter> - <parameter name="maxConnPerRoute">10</parameter> + <!-- Connection Management: sized for concurrent large-payload fan-out --> + <parameter name="maxConnTotal">64</parameter> + <parameter name="maxConnPerRoute">32</parameter> <!-- Timeouts for Large Payloads --> <parameter name="connectionTimeout">30000</parameter> diff --git a/src/site/xdoc/docs/wildfly-http2-integration-guide.xml b/src/site/xdoc/docs/wildfly-http2-integration-guide.xml index c8e944f535..d7adef6f23 100644 --- a/src/site/xdoc/docs/wildfly-http2-integration-guide.xml +++ b/src/site/xdoc/docs/wildfly-http2-integration-guide.xml @@ -48,15 +48,29 @@ WildFly 39 is compatible with the same configuration.</p> <h2>WildFly Server-Level HTTP/2 Configuration (RECOMMENDED)</h2> <div style="background-color: #e8f5e8; border: 1px solid #4CAF50; padding: 10px; margin: 10px 0;"> -<strong>🎯 Key Optimizations:</strong> +<strong>Key Optimizations:</strong> <ul> - <li><strong>64KB Buffer Alignment</strong> - Consistent across all layers (WildFly + Enhanced Moshi/GSON H2)</li> - <li><strong>128KB HTTP/2 Windows</strong> - Optimized for 50MB+ JSON payload processing</li> + <li><strong>64KB Buffer/Flush Alignment</strong> - WildFly byte-buffer-pool and FlushingOutputStream flush interval are aligned at 64KB. This is a server-side serialization setting and is correct.</li> + <li><strong>HTTP/2 Flow-Control Windows</strong> - Sized for payload, not aligned to flush interval. See + <a href="http2-transport-additions.html#H2TransportSender">HTTP/2 Transport configuration</a> + for guidance on <code>initialWindowSize</code> tuning.</li> <li><strong>Minimal Protocol Overhead</strong> - Single-layer HTTP/2 processing architecture</li> <li><strong>Enhanced Monitoring</strong> - Built-in performance tracking and access logging</li> </ul> </div> +<div style="background-color: #fff8e1; border: 1px solid #f9a825; padding: 10px; margin: 10px 0;"> +<strong>Important:</strong> The Axis2 transport's +<code>initialWindowSize</code> should <strong>not</strong> be set to +64KB to match the WildFly buffer pool or FlushingOutputStream flush +interval. The flow-control window and the server-side flush interval are +independent — a 64KB window forces ~156 WINDOW_UPDATE round-trips for a +10MB response. Use at least 2MB for general traffic or 8MB for +large-payload workloads. See +<a href="http2-transport-additions.html#H2TransportSender">HTTP/2 Transport +— Tuning for Different Workloads</a>. +</div> + <pre> <subsystem xmlns="urn:jboss:domain:undertow:14.0" default-virtual-host="default-host"
