From 1a7890ee4d6e198cfff7202a2fe4de3d7e24b6ed Mon Sep 17 00:00:00 2001 From: annie-mac Date: Mon, 25 Nov 2024 14:59:21 -0800 Subject: [PATCH] add enableHttp2PublicAPI --- .../com/azure/cosmos/rx/TestSuiteBase.java | 10 ++ .../azure/cosmos/GatewayConnectionConfig.java | 23 ++++ .../azure/cosmos/Http2ConnectionConfig.java | 123 ++++++++++++++++++ .../implementation/ConnectionPolicy.java | 24 ++++ .../implementation/RxDocumentClientImpl.java | 2 +- .../implementation/http/HttpClient.java | 10 ++ .../implementation/http/HttpClientConfig.java | 12 +- .../http/ReactorNettyClient.java | 4 +- .../main/java/com/azure/cosmos/util/Beta.java | 4 +- 9 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/Http2ConnectionConfig.java diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/TestSuiteBase.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/TestSuiteBase.java index 82d78e196cac4..c25e46620f6a5 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/TestSuiteBase.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/TestSuiteBase.java @@ -20,6 +20,7 @@ import com.azure.cosmos.CosmosResponseValidator; import com.azure.cosmos.DirectConnectionConfig; import com.azure.cosmos.GatewayConnectionConfig; +import com.azure.cosmos.Http2ConnectionConfig; import com.azure.cosmos.TestNGLogListener; import com.azure.cosmos.ThrottlingRetryOptions; import com.azure.cosmos.implementation.Configs; @@ -1444,6 +1445,15 @@ static protected CosmosClientBuilder createGatewayRxDocumentClient( boolean retryOnThrottledRequests) { GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig(); + if (Configs.isHttp2Enabled()) { + Http2ConnectionConfig http2ConnectionConfig = new Http2ConnectionConfig() + .setEnabled(true) + .setMaxConnectionPoolSize(10) + .setMinConnectionPoolSize(1) + .setMaxConcurrentStreams(30); + gatewayConnectionConfig.setHttp2ConnectionConfig(http2ConnectionConfig); + } + CosmosClientBuilder builder = new CosmosClientBuilder().endpoint(endpoint) .credential(credential) .gatewayMode(gatewayConnectionConfig) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/GatewayConnectionConfig.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/GatewayConnectionConfig.java index 69003850868c8..3ed9faa4e39a6 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/GatewayConnectionConfig.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/GatewayConnectionConfig.java @@ -5,6 +5,7 @@ import com.azure.core.http.ProxyOptions; import com.azure.cosmos.implementation.Configs; +import com.azure.cosmos.util.Beta; import java.time.Duration; @@ -24,6 +25,7 @@ public final class GatewayConnectionConfig { private int maxConnectionPoolSize; private Duration idleConnectionTimeout; private ProxyOptions proxy; + private Http2ConnectionConfig http2ConnectionConfig; /** * Constructor. @@ -32,6 +34,7 @@ public GatewayConnectionConfig() { this.idleConnectionTimeout = DEFAULT_IDLE_CONNECTION_TIMEOUT; this.maxConnectionPoolSize = Configs.getDefaultHttpPoolSize(); this.networkRequestTimeout = DEFAULT_NETWORK_REQUEST_TIMEOUT; + this.http2ConnectionConfig = new Http2ConnectionConfig(); } /** @@ -136,6 +139,25 @@ public GatewayConnectionConfig setProxy(ProxyOptions proxy) { return this; } + /*** + * Get the http2 connection config. + * @return the {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig getHttp2ConnectionConfig() { + return http2ConnectionConfig; + } + + /*** + * Set the http2 connection config. + * @param http2ConnectionConfig the {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public GatewayConnectionConfig setHttp2ConnectionConfig(Http2ConnectionConfig http2ConnectionConfig) { + this.http2ConnectionConfig = http2ConnectionConfig; + return this; + } + @Override public String toString() { String proxyType = proxy != null ? proxy.getType().toString() : null; @@ -147,6 +169,7 @@ public String toString() { ", networkRequestTimeout=" + networkRequestTimeout + ", proxyType=" + proxyType + ", inetSocketProxyAddress=" + proxyAddress + + ", http2ConnectionConfig=" + http2ConnectionConfig.toString() + '}'; } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/Http2ConnectionConfig.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/Http2ConnectionConfig.java new file mode 100644 index 0000000000000..162f2328a17fb --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/Http2ConnectionConfig.java @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.cosmos; + +import com.azure.cosmos.implementation.Configs; +import com.azure.cosmos.util.Beta; + +@Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) +public class Http2ConnectionConfig { + private static final int DEFAULT_MAX_CONCURRENT_STREAMS = 30; + private static final int DEFAULT_MIN_CONNECTION_POOL_SIZE = 1; + + private int maxConnectionPoolSize; + private int minConnectionPoolSize; + private int maxConcurrentStreams; + private boolean enabled; + + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig() { + this.maxConnectionPoolSize = Configs.getDefaultHttpPoolSize(); // overlapping with the maxConnectionPoolSize in gateway connection config + this.minConnectionPoolSize = DEFAULT_MIN_CONNECTION_POOL_SIZE; + this.maxConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS; + this.enabled = Configs.isHttp2Enabled(); + } + + /*** + * Get the maximum number of live connections to keep in the pool. + * + * @return the configured max number of live connections to keep in the pool. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Integer getMaxConnectionPoolSize() { + return maxConnectionPoolSize; + } + + /*** + * Configures the maximum number of live connections to keep in the pool. + * If not configured, will be default to 1000. + * + * @param maxConnectionPoolSize the maximum number of live connections to keep in the pool. + * @return the current {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig setMaxConnectionPoolSize(int maxConnectionPoolSize) { + this.maxConnectionPoolSize = maxConnectionPoolSize; + return this; + } + + /*** + * Get the maximum number of the concurrent streams that can be opened to the remote peer. + * @return the maximum number of the concurrent streams that can be opened to the remote peer. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public int getMaxConcurrentStreams() { + return maxConcurrentStreams; + } + + /*** + * Configures the maximum number of the concurrent streams that can be opened to the remote peer. + * When evaluating how many streams can be opened to the remote peer, the minimum of this configuration and the remote peer configuration is taken (unless -1 is used). + * Default to 30. + * + * @param maxConcurrentStreams the maximum number of the concurrent streams that can be opened to the remote peer. + * @return the current {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig setMaxConcurrentStreams(int maxConcurrentStreams) { + this.maxConcurrentStreams = maxConcurrentStreams; + return this; + } + + /*** + * Get the minimum number of live connections to keep in the pool (can be the best effort). + * @return the minimum number of live connections to keep in the pool (can be the best effort). + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public int getMinConnectionPoolSize() { + return minConnectionPoolSize; + } + + /*** + * Configures the minimum number of live connections to keep in the pool (can be the best effort). Default to 1. + * @param minConnectionPoolSize the minimum number of live connections to keep in the pool (can be the best effort). + * @return the current {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig setMinConnectionPoolSize(int minConnectionPoolSize) { + this.minConnectionPoolSize = minConnectionPoolSize; + return this; + } + + /*** + * return the flag to indicate whether http2 is enabled. + * @return the flag to indicate whether http2 is enabled. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public boolean isEnabled() { + return enabled; + } + + /*** + * Configure the flag to indicate whether http2 is enabled. + * @param enabled the flag to indicate whether http2 is enabled. + * @return the current {@link Http2ConnectionConfig}. + */ + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Http2ConnectionConfig setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + @Beta(value = Beta.SinceVersion.V4_66_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + @Override + public String toString() { + return "Http2ConnectionConfig{" + + "isEnabled=" + enabled + + ", maxConnectionPoolSize=" + maxConnectionPoolSize + + ", minConnectionPoolSize=" + minConnectionPoolSize + + ", maxConcurrentStreams=" + maxConcurrentStreams + + '}'; + } +} diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ConnectionPolicy.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ConnectionPolicy.java index 7cad767ece975..8335334cb7196 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ConnectionPolicy.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ConnectionPolicy.java @@ -9,7 +9,9 @@ import com.azure.cosmos.CosmosExcludedRegions; import com.azure.cosmos.DirectConnectionConfig; import com.azure.cosmos.GatewayConnectionConfig; +import com.azure.cosmos.Http2ConnectionConfig; import com.azure.cosmos.ThrottlingRetryOptions; +import reactor.netty.Connection; import java.time.Duration; import java.util.Collections; @@ -38,6 +40,7 @@ public final class ConnectionPolicy { private Duration httpNetworkRequestTimeout; private ProxyOptions proxy; private Duration idleHttpConnectionTimeout; + private Http2ConnectionConfig http2ConnectionConfig; // Direct connection config properties private Duration connectTimeout; @@ -100,6 +103,7 @@ private ConnectionPolicy( .DirectConnectionConfigHelper .getDirectConnectionConfigAccessor() .isHealthCheckTimeoutDetectionEnabled(directConnectionConfig); + this.http2ConnectionConfig = gatewayConnectionConfig.getHttp2ConnectionConfig(); // NOTE: should be compared with COSMOS.MIN_CONNECTION_POOL_SIZE_PER_ENDPOINT // read during client initialization before connections are created for the container @@ -635,6 +639,25 @@ public boolean isServerCertValidationDisabled() { return this.serverCertValidationDisabled; } + /*** + * Get the Http2ConnectionConfig for gateway request. + * @return the configured {@link Http2ConnectionConfig}. + */ + public Http2ConnectionConfig getHttp2ConnectionConfig() { + return http2ConnectionConfig; + } + + /*** + * Set the Http2ConnectionConfig for gateway request. + * + * @param http2ConnectionConfig the configured http2ConnectionConfig. + * @return the current {@link ConnectionPolicy}. + */ + public ConnectionPolicy setHttp2ConnectionConfig(Http2ConnectionConfig http2ConnectionConfig) { + this.http2ConnectionConfig = http2ConnectionConfig; + return this; + } + @Override public String toString() { return "ConnectionPolicy{" + @@ -663,6 +686,7 @@ public String toString() { ", minConnectionPoolSizePerEndpoint=" + minConnectionPoolSizePerEndpoint + ", openConnectionsConcurrency=" + openConnectionsConcurrency + ", aggressiveWarmupConcurrency=" + aggressiveWarmupConcurrency + + ", http2ConnectionConfig=" + this.http2ConnectionConfig.toString() + '}'; } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java index 83ff0114f2197..4a8da0e4da64f 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java @@ -832,7 +832,7 @@ private HttpClient httpClient() { .withProxy(this.connectionPolicy.getProxy()) .withNetworkRequestTimeout(this.connectionPolicy.getHttpNetworkRequestTimeout()) .withServerCertValidationDisabled(this.connectionPolicy.isServerCertValidationDisabled()) - .withHttp2Enabled(Configs.isHttp2Enabled()); + .withHttp2Config(this.connectionPolicy.getHttp2ConnectionConfig()); if (connectionSharingAcrossClientsEnabled) { return SharedGatewayHttpClient.getOrCreateInstance(httpClientConfig, diagnosticsClientConfig); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClient.java index 1054e3098ed3c..91df58db6b70f 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClient.java @@ -3,6 +3,7 @@ package com.azure.cosmos.implementation.http; import reactor.core.publisher.Mono; +import reactor.netty.http.client.Http2AllocationStrategy; import reactor.netty.resources.ConnectionProvider; import java.time.Duration; @@ -46,6 +47,15 @@ static HttpClient createFixed(HttpClientConfig httpClientConfig) { fixedConnectionProviderBuilder.maxIdleTime(httpClientConfig.getMaxIdleConnectionTimeout()); // TODO[Http2]: config Http2AllocationStrategy (maxConnections & maxConcurrentStreams) + if (httpClientConfig.getHttp2ConnectionConfig().isEnabled()) { + fixedConnectionProviderBuilder.allocationStrategy( + Http2AllocationStrategy.builder() + .minConnections(httpClientConfig.getHttp2ConnectionConfig().getMinConnectionPoolSize()) + .maxConnections(httpClientConfig.getHttp2ConnectionConfig().getMaxConnectionPoolSize()) + .maxConcurrentStreams(httpClientConfig.getHttp2ConnectionConfig().getMaxConcurrentStreams()) + .build() + ); + } return ReactorNettyClient.createWithConnectionProvider(fixedConnectionProviderBuilder.build(), httpClientConfig); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClientConfig.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClientConfig.java index f77ebe6108d83..acdd97f8d1d3b 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClientConfig.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/HttpClientConfig.java @@ -4,7 +4,9 @@ package com.azure.cosmos.implementation.http; import com.azure.core.http.ProxyOptions; +import com.azure.cosmos.Http2ConnectionConfig; import com.azure.cosmos.implementation.Configs; +import com.azure.cosmos.util.Beta; import java.time.Duration; @@ -27,7 +29,7 @@ public class HttpClientConfig { private ProxyOptions proxy; private boolean connectionKeepAlive = true; private boolean serverCertValidationDisabled = false; - private boolean http2Enabled; + private Http2ConnectionConfig http2ConnectionConfig; public HttpClientConfig(Configs configs) { this.configs = configs; @@ -98,8 +100,8 @@ public HttpClientConfig withServerCertValidationDisabled(boolean serverCertValid return this; } - public HttpClientConfig withHttp2Enabled(boolean http2Enabled) { - this.http2Enabled = http2Enabled; + public HttpClientConfig withHttp2Config(Http2ConnectionConfig http2ConnectionConfig) { + this.http2ConnectionConfig = http2ConnectionConfig; return this; } @@ -159,8 +161,8 @@ public boolean isServerCertValidationDisabled() { return serverCertValidationDisabled; } - public boolean isHttp2Enabled() { - return http2Enabled; + public Http2ConnectionConfig getHttp2ConnectionConfig() { + return this.http2ConnectionConfig; } public String toDiagnosticsString() { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java index c12f6c12b130e..509651d1aca73 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java @@ -149,13 +149,13 @@ private void configureChannelPipelineHandlers() { .maxChunkSize(this.httpClientConfig.getMaxChunkSize()) .validateHeaders(true)); - if (httpClientConfig.isHttp2Enabled()) { + if (httpClientConfig.getHttp2ConnectionConfig().isEnabled()) { this.httpClient = this.httpClient .secure(sslContextSpec -> sslContextSpec.sslContext( configs.getSslContext( httpClientConfig.isServerCertValidationDisabled(), - httpClientConfig.isHttp2Enabled() + true ))) .protocol(HttpProtocol.H2, HttpProtocol.HTTP11) .doOnConnected((connection -> { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/util/Beta.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/util/Beta.java index c4134ed39f0e6..b3c9804b9a81b 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/util/Beta.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/util/Beta.java @@ -101,6 +101,8 @@ public enum SinceVersion { /** v4.64.0 */ V4_64_0, /** v4.65.0 */ - V4_65_0 + V4_65_0, + /** v4.66.0 */ + V4_66_0 } }