| <!-- |
| ~ Licensed to the Apache Software Foundation (ASF) under one |
| ~ or more contributor license agreements. See the NOTICE file |
| ~ distributed with this work for additional information |
| ~ regarding copyright ownership. The ASF licenses this file |
| ~ to you 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. |
| --> |
| |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" |
| "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml" version="-//W3C//DTDXHTML1.1//EN"> |
| <head> |
| <meta http-equiv="content-type" content=""/> |
| <title>HTTP/2 Transport</title> |
| </head> |
| |
| <body lang="en"> |
| |
| <a name="H2TransportSender"></a> |
| <h2>H2TransportSender (HTTP/2 Transport)</h2> |
| |
| <h3>🚀 TL;DR - Quick Start for Large Payloads (50MB+)</h3> |
| |
| <p><strong>Most Common Use Case:</strong> Processing 50MB+ JSON payloads with optimal performance</p> |
| |
| <p><strong>Production Configuration (axis2.xml) - AWS/Cloudflare Ready:</strong></p> |
| <pre> |
| <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> |
| <parameter name="PROTOCOL">HTTP/2.0</parameter> |
| |
| <!-- ALPN Support (Required for AWS ALB, Cloudflare) --> |
| <parameter name="alpnProtocols">h2,http/1.1</parameter> |
| <parameter name="tlsRequired">true</parameter> |
| |
| <!-- Large Payload Optimization --> |
| <parameter name="maxConcurrentStreams">20</parameter> |
| <parameter name="initialWindowSize">2097152</parameter> <!-- 2MB window --> |
| <!-- Timeouts --> |
| <parameter name="connectionTimeout">30000</parameter> <!-- 30s connect --> |
| <parameter name="responseTimeout">300000</parameter> <!-- 5min response --> |
| |
| <!-- HTTP/2 fallback to HTTP/1.1 is automatic via TLS ALPN --> |
| </transportSender> |
| </pre> |
| |
| <p><strong>Client Access for 50MB JSON Payloads:</strong></p> |
| <p>Most JSON clients will use <strong>curl</strong> or <strong>Apache HTTP Components</strong> directly:</p> |
| |
| <pre> |
| # curl with HTTP/2 for large JSON payloads (AWS/Cloudflare compatible) |
| curl --http2-prior-knowledge -X POST \ |
| -H "Content-Type: application/json" \ |
| -H "Accept: application/json" \ |
| -H "User-Agent: MyApp/1.0" \ |
| --max-time 300 --connect-timeout 30 \ |
| --compressed \ |
| --data @large-payload.json \ |
| https://server:8443/services/BigDataService |
| |
| # Apache HTTP Components 5.x (Java clients) |
| CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom() |
| .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2) |
| .build(); |
| httpClient.start(); |
| |
| HttpPost request = new HttpPost("https://server:8443/services/BigDataService"); |
| request.setEntity(new StringEntity(jsonPayload, ContentType.APPLICATION_JSON)); |
| </pre> |
| |
| <p><strong>Expected Performance:</strong> 40-70% faster than HTTP/1.1 for 50MB+ JSON payloads with 20% less memory usage</p> |
| |
| <p><strong>Note:</strong> Server push is disabled by default as it's not beneficial for JSON APIs |
| (see "Server Push Capabilities" section below for detailed explanation).</p> |
| |
| <hr/> |
| |
| <p>H2TransportSender provides enterprise-grade HTTP/2 transport capabilities using HttpClient 5.x |
| with advanced features for large payload processing, connection multiplexing, and performance optimization. |
| This transport is specifically designed for big data applications requiring 50MB+ JSON payload support |
| with memory-efficient 64 KB flush intervals.</p> |
| |
| <p>HTTP/2 offers significant advantages over HTTP/1.1:</p> |
| <ul> |
| <li>Binary protocol with header compression (HPACK)</li> |
| <li>Stream multiplexing - multiple concurrent requests over single connection</li> |
| <li>Server push capabilities (configurable)</li> |
| <li>Improved flow control with window scaling</li> |
| <li>Enhanced performance for large payloads</li> |
| <li>Reduced connection overhead and latency</li> |
| </ul> |
| |
| <h3>Basic HTTP/2 Configuration</h3> |
| |
| <p>The <transportSender/> element for HTTP/2 transport:</p> |
| <pre> |
| <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">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. 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>streamingBufferSize</td><td>Buffer size for streaming flush interval</td><td>65536</td><td>8KB-1MB</td></tr> |
| <tr><td>connectionTimeout</td><td>Connection establishment timeout (ms)</td><td>30000</td><td>1000-60000</td></tr> |
| <tr><td>responseTimeout</td><td>Response timeout for large payloads (ms)</td><td>300000</td><td>30000-600000</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. |
| 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: 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 --> |
| <parameter name="streamingBufferSize">65536</parameter> |
| <parameter name="memoryOptimized">true</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> |
| <parameter name="responseTimeout">300000</parameter> |
| </transportSender> |
| </pre> |
| |
| <h3>HTTPS with HTTP/2 (ALPN)</h3> |
| |
| <p>HTTP/2 over HTTPS requires Application-Layer Protocol Negotiation (ALPN). The H2TransportSender |
| automatically handles ALPN negotiation when used with HTTPS endpoints:</p> |
| |
| <pre> |
| <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> |
| <parameter name="PROTOCOL">HTTP/2.0</parameter> |
| <parameter name="tlsRequired">true</parameter> |
| <parameter name="alpnProtocols">h2,http/1.1</parameter> |
| </transportSender> |
| </pre> |
| |
| <h3>Stream Multiplexing Configuration</h3> |
| |
| <p>HTTP/2 stream multiplexing allows multiple concurrent requests over a single connection, |
| significantly improving performance for concurrent operations:</p> |
| |
| <pre> |
| // Enable HTTP/2 multiplexing in client code |
| Options options = new Options(); |
| options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2"); |
| // HTTP/2 multiplexing is automatic when using the h2 transport. |
| // No additional boolean flags are needed. |
| </pre> |
| |
| <h3>Large Payload Processing</h3> |
| |
| <p>The H2TransportSender provides three processing modes optimized for different payload sizes:</p> |
| |
| <ul> |
| <li><strong>Standard Processing</strong> (0MB-10MB): Regular HTTP/2 features</li> |
| <li><strong>Multiplexing Mode</strong> (10-50MB): Enhanced concurrent processing</li> |
| <li><strong>Streaming Mode</strong> (50MB+): Memory-efficient streaming with chunked processing</li> |
| </ul> |
| |
| <p>Streaming and memory optimization are controlled by the message formatter |
| selected in axis2.xml (e.g. <code>MoshiStreamingMessageFormatter</code>). |
| No client-side <code>Options</code> properties are required — the transport |
| sender negotiates HTTP/2 framing and flow control automatically.</p> |
| |
| <h3>Performance Monitoring</h3> |
| |
| <p>For production monitoring, use Micrometer with Prometheus/Grafana or |
| Spring Boot Actuator endpoints. Application-level logging via the |
| Axis2 log configuration provides per-request timing details.</p> |
| |
| <p>Available metrics include:</p> |
| <ul> |
| <li>Stream allocation and utilization</li> |
| <li>Memory usage and buffer efficiency</li> |
| <li>Processing time and throughput</li> |
| <li>Compression ratios and bandwidth savings</li> |
| <li>Connection reuse statistics</li> |
| </ul> |
| |
| <h3>Flow Control</h3> |
| |
| <p>HTTP/2 flow control is handled automatically by the transport layer. |
| The <code>initialWindowSize</code> parameter on the transport sender controls |
| the initial flow-control window; beyond that, the HTTP/2 implementation |
| manages window updates and back-pressure without additional configuration.</p> |
| |
| <h3>Compression</h3> |
| |
| <p>Response compression is handled by the servlet container (Tomcat, WildFly, etc.), |
| not by the Axis2 transport. Configure compression in your container's server |
| configuration (e.g., Tomcat's <code>server.xml</code> <code>compression</code> |
| attribute, or WildFly's Undertow content-encoding filter). HTTP/2 header |
| compression (HPACK) is always active and requires no Axis2 configuration.</p> |
| |
| <h3>Memory Management</h3> |
| |
| <p>Buffer management is handled internally by Apache HttpComponents 5.x. |
| The JVM's default direct memory limit (equal to <code>-Xmx</code>) is |
| sufficient for most deployments. No additional JVM flags are needed |
| for HTTP/2 buffer management.</p> |
| |
| <h3>Error Handling and Fallback</h3> |
| |
| <p>When the remote server does not support HTTP/2, the TLS ALPN negotiation |
| falls back to HTTP/1.1 automatically. No explicit fallback parameters are |
| required — Apache HttpComponents handles protocol negotiation.</p> |
| |
| <h3>Server Push</h3> |
| |
| <p>Server push is <strong>disabled by default</strong> — REST/JSON APIs follow |
| request-response patterns where push provides no benefit. Enable only |
| for web-app use cases with predictable resource dependencies:</p> |
| <pre> |
| <parameter name="serverPushEnabled">false</parameter> <!-- default --> |
| </pre> |
| |
| <h3>Service-Level HTTP/2 Configuration</h3> |
| |
| <p>Individual services can specify HTTP/2 preferences in their services.xml:</p> |
| |
| <p>HTTP/2 is enabled at the transport level in axis2.xml, not per-service. |
| Select the H2TransportSender in the <code><transportSender></code> section |
| and configure its parameters there. For streaming large payloads, use the |
| streaming message formatter (e.g. <code>MoshiStreamingMessageFormatter</code> |
| or <code>JSONStreamingMessageFormatter</code>) in the service's message |
| receiver configuration. No service-level parameters are required.</p> |
| |
| <h3>Client-Side HTTP/2 Usage for SOAP (for JSON, see curl and Apache HTTPComponents section)</h3> |
| |
| <p>Complete client configuration example:</p> |
| |
| <pre> |
| // Create HTTP/2 enabled service client |
| ConfigurationContext configContext = ConfigurationContextFactory |
| .createConfigurationContextFromFileSystem(null, null); |
| |
| ServiceClient serviceClient = new ServiceClient(configContext, null); |
| |
| // Configure HTTP/2 transport |
| Options options = new Options(); |
| options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2"); |
| options.setTo(new EndpointReference("https://localhost:8443/services/BigDataService")); |
| |
| // HTTP/2 is negotiated by the transport sender selected in axis2.xml. |
| // No additional boolean flags are needed — the h2 transport handles |
| // multiplexing, streaming, and flow control automatically. |
| |
| // Timeout settings for large payloads |
| options.setTimeOutInMilliSeconds(300000); // 5 minutes |
| options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, 30000); |
| options.setProperty(HTTPConstants.SO_TIMEOUT, 300000); |
| |
| serviceClient.setOptions(options); |
| </pre> |
| |
| <h3>Performance Comparison: HTTP/1.1 vs HTTP/2</h3> |
| |
| <p>HTTP/2 transport can provide substantial improvements over HTTP/1.1. |
| The following are illustrative estimates — actual results depend on payload size, |
| network conditions, and JVM configuration:</p> |
| |
| <table border="1"> |
| <tr><th>Metric</th><th>HTTP/1.1</th><th>HTTP/2</th><th>Improvement</th></tr> |
| <tr><td>Connection Multiplexing</td><td>6-8 connections</td><td>100 concurrent streams</td><td>1,150-1,567%</td></tr> |
| <tr><td>Memory Efficiency</td><td>Standard allocation</td><td>Pooled buffers</td><td>30-50%</td></tr> |
| <tr><td>Large Payload (50MB)</td><td>Baseline</td><td>Streaming optimization</td><td>50-200%</td></tr> |
| <tr><td>Compression</td><td>Basic gzip</td><td>JSON-aware optimization</td><td>50-70%</td></tr> |
| <tr><td>Overall Throughput</td><td>Baseline</td><td>Combined optimizations</td><td>70-150%</td></tr> |
| </table> |
| |
| <h3>Troubleshooting HTTP/2</h3> |
| |
| <p>Common HTTP/2 configuration issues and solutions:</p> |
| |
| <h4>ALPN Not Available</h4> |
| <pre> |
| // Ensure ALPN support is available |
| System.setProperty("java.security.properties", "jdk.tls.alpnCharset=UTF-8"); |
| </pre> |
| |
| <h4>Memory Issues with Large Payloads</h4> |
| <pre> |
| // Increase heap size for large JSON payloads |
| -Xmx4g -XX:+UseG1GC |
| </pre> |
| |
| <h4>Connection Issues</h4> |
| <p>HTTP/2 fallback to HTTP/1.1 is automatic via TLS ALPN negotiation. |
| If the server does not advertise h2, the client falls back transparently. |
| Increase <code>connectionTimeout</code> on the transport sender if ALPN |
| negotiation is slow on your network.</p> |
| |
| <h3>Migration from HTTP/1.1 to HTTP/2</h3> |
| |
| <p>To migrate existing HTTP/1.1 configurations to HTTP/2:</p> |
| |
| <ol> |
| <li>Change transport sender class to H2TransportSender</li> |
| <li>Update protocol parameter to HTTP/2.0</li> |
| <li>Add HTTP/2 specific parameters</li> |
| <li>Configure HTTPS with ALPN support</li> |
| <li>Test with fallback enabled</li> |
| </ol> |
| |
| <p>Example migration:</p> |
| <pre> |
| <!-- HTTP/1.1 Configuration --> |
| <transportSender name="http" class="org.apache.axis2.transport.http.impl.httpclient5.HTTPClient5TransportSender"> |
| <parameter name="PROTOCOL">HTTP/1.1</parameter> |
| <parameter name="Transfer-Encoding">chunked</parameter> |
| </transportSender> |
| |
| <!-- HTTP/2 Configuration --> |
| <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">2097152</parameter> |
| <!-- Fallback to HTTP/1.1 is automatic via TLS ALPN negotiation --> |
| </transportSender> |
| </pre> |
| |
| <h3>SSL Client Authentication (2-Way SSL) with HTTP/2</h3> |
| |
| <p>HTTP/2 transport supports SSL client authentication (mutual TLS) similar to HTTP/1.1, with enhanced |
| features for certificate management and ALPN negotiation. You can configure your own HttpAsyncClient |
| with custom SSL context and certificate handling.</p> |
| |
| <p>The HTTP/2 transport supports the same certificate management as HTTP/1.1 but uses async client |
| architecture. To control max connections per host, SSL configuration, or other advanced parameters, |
| set the cached HTTP/2 client using the CACHED_HTTP2_ASYNC_CLIENT property before making requests.</p> |
| |
| <p>The following example shows SSL client authentication configuration tested with Axis2 on WildFly 32:</p> |
| |
| <pre> |
| // Certificate and TrustStore setup (same as HTTP/1.1) |
| String wildflyserver_cert_path = "src/wildflyserver.crt"; |
| Certificate certificate = CertificateFactory.getInstance("X.509") |
| .generateCertificate(new FileInputStream(new File(wildflyserver_cert_path))); |
| KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| keyStore.load(null, null); |
| keyStore.setCertificateEntry("server", certificate); |
| |
| TrustManagerFactory trustManagerFactory = null; |
| trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
| trustManagerFactory.init(keyStore); |
| TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); |
| if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { |
| throw new Exception("Unexpected default trust managers:" + Arrays.toString(trustManagers)); |
| } |
| |
| // SSL Context with TLS 1.3 support for HTTP/2 |
| SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); |
| sslContext.init(null, trustManagers, new SecureRandom()); |
| |
| // HTTP/2 specific TLS strategy with ALPN support |
| TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() |
| .setSslContext(sslContext) |
| .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) // For self-signed certificates |
| .setTlsDetailsFactory(sslEngine -> { |
| // Configure ALPN protocols for HTTP/2 negotiation |
| SSLParameters sslParams = sslEngine.getSSLParameters(); |
| sslParams.setApplicationProtocols(new String[]{"h2", "http/1.1"}); |
| sslEngine.setSSLParameters(sslParams); |
| return null; |
| }) |
| .build(); |
| |
| // HTTP/2 async connection manager with SSL configuration |
| PoolingAsyncClientConnectionManager connManager = PoolingAsyncClientConnectionManagerBuilder.create() |
| .setTlsStrategy(tlsStrategy) |
| .setMaxConnTotal(100) |
| .setMaxConnPerRoute(100) |
| .build(); |
| |
| // Create HTTP/2 async client with SSL configuration |
| CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom() |
| .setConnectionManager(connManager) |
| .setConnectionManagerShared(true) |
| .setVersionPolicy(HttpVersionPolicy.NEGOTIATE) // Allow HTTP/2 negotiation |
| .build(); |
| |
| httpAsyncClient.start(); // Important: Start the async client |
| |
| // Configure service client with HTTP/2 SSL client |
| Options options = new Options(); |
| options.setTo(new EndpointReference("https://myserver:8443/services/MyService")); |
| options.setProperty(HTTPConstants.TRANSPORT_NAME, "h2"); // Use HTTP/2 transport |
| options.setTimeOutInMilliSeconds(120000); |
| |
| // Set the cached HTTP/2 async client (HTTP/2 equivalent of CACHED_HTTP_CLIENT) |
| options.setProperty("CACHED_HTTP2_ASYNC_CLIENT", httpAsyncClient); |
| |
| ServiceClient sender = new ServiceClient(); |
| sender.setOptions(options); |
| </pre> |
| |
| <h3>HTTP/2 SSL Configuration Parameters</h3> |
| |
| <p>The HTTP/2 transport provides additional SSL-specific parameters:</p> |
| |
| <table border="1"> |
| <tr><th>Parameter</th><th>Description</th><th>Default</th><th>HTTP/1.1 Equivalent</th></tr> |
| <tr><td>CACHED_HTTP2_ASYNC_CLIENT</td><td>Custom HTTP/2 async client with SSL config</td><td>None</td><td>CACHED_HTTP_CLIENT</td></tr> |
| <tr><td>tlsRequired</td><td>Enforce HTTPS-only for HTTP/2</td><td>true</td><td>N/A</td></tr> |
| <tr><td>alpnProtocols</td><td>ALPN protocol preferences</td><td>h2,http/1.1</td><td>N/A</td></tr> |
| <tr><td>supportedTLSVersions</td><td>Supported TLS versions</td><td>TLSv1.2,TLSv1.3</td><td>Similar</td></tr> |
| <tr><td>cipherSuites</td><td>Allowed cipher suites</td><td>TLS 1.3 defaults</td><td>Similar</td></tr> |
| </table> |
| |
| <h3>Advanced SSL Configuration for HTTP/2</h3> |
| |
| <p>For enterprise deployments requiring specific SSL configurations:</p> |
| |
| <pre> |
| <transportSender name="h2" class="org.apache.axis2.transport.h2.impl.httpclient5.H2TransportSender"> |
| <parameter name="PROTOCOL">HTTP/2.0</parameter> |
| |
| <!-- SSL/TLS Configuration --> |
| <parameter name="tlsRequired">true</parameter> |
| <parameter name="supportedTLSVersions">TLSv1.2,TLSv1.3</parameter> |
| <parameter name="alpnProtocols">h2,http/1.1</parameter> |
| |
| <!-- ALPN Configuration --> |
| <parameter name="alpnTimeout">5000</parameter> |
| <parameter name="alpnFallbackEnabled">true</parameter> |
| |
| <!-- Certificate Validation --> |
| <parameter name="hostnameVerification">strict</parameter> |
| <parameter name="certificateValidation">strict</parameter> |
| </transportSender> |
| </pre> |
| |
| <h3>Client Certificate Authentication</h3> |
| |
| <p>For mutual TLS (client certificate authentication) with HTTP/2:</p> |
| |
| <pre> |
| // Load client certificate and private key |
| KeyStore clientKeyStore = KeyStore.getInstance("PKCS12"); |
| clientKeyStore.load(new FileInputStream("client-cert.p12"), "password".toCharArray()); |
| |
| KeyManagerFactory keyManagerFactory = KeyManagerFactory |
| .getInstance(KeyManagerFactory.getDefaultAlgorithm()); |
| keyManagerFactory.init(clientKeyStore, "password".toCharArray()); |
| |
| // SSL Context with client certificate |
| SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); |
| sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom()); |
| |
| // Configure HTTP/2 client with client certificate authentication |
| TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() |
| .setSslContext(sslContext) |
| .setTlsDetailsFactory(sslEngine -> { |
| SSLParameters sslParams = sslEngine.getSSLParameters(); |
| sslParams.setApplicationProtocols(new String[]{"h2", "http/1.1"}); |
| sslParams.setNeedClientAuth(true); // Require client authentication |
| sslEngine.setSSLParameters(sslParams); |
| return null; |
| }) |
| .build(); |
| </pre> |
| |
| <h3>HTTP/2 vs HTTP/1.1 SSL Differences</h3> |
| |
| <p>Key differences in SSL handling between HTTP/1.1 and HTTP/2:</p> |
| |
| <ul> |
| <li><strong>ALPN Support</strong>: HTTP/2 requires ALPN negotiation for protocol selection</li> |
| <li><strong>TLS Version</strong>: HTTP/2 requires TLS 1.2 or higher (TLS 1.3 recommended)</li> |
| <li><strong>Cipher Suites</strong>: HTTP/2 has specific cipher suite requirements (RFC 7540)</li> |
| <li><strong>Async Architecture</strong>: Uses CloseableHttpAsyncClient instead of CloseableHttpClient</li> |
| <li><strong>Connection Multiplexing</strong>: Single SSL connection handles multiple streams</li> |
| <li><strong>Fallback Handling</strong>: Automatic fallback to HTTP/1.1 if HTTP/2 negotiation fails</li> |
| </ul> |
| |
| <h3>SSL Notes</h3> |
| |
| <p>HTTP/2 requires TLS 1.2+ with ALPN. Use OpenJDK 11+ (ALPN built in). |
| If ALPN negotiation fails, the transport falls back to HTTP/1.1 |
| automatically (no configuration flag required).</p> |
| |
| </body> |
| </html> |