diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java index 89885ae320f6..54b0a0c2ef30 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java @@ -170,11 +170,11 @@ public void http2MaxConcurrentStreams() { @Test(groups = { "emulator" }) public void thinClientEnabledTest() { - assertThat(isThinClientEnabled()).isFalse(); + assertThat(isThinClientEnabled()).isTrue(); System.clearProperty("COSMOS.THINCLIENT_ENABLED"); - System.setProperty("COSMOS.THINCLIENT_ENABLED", "true"); + System.setProperty("COSMOS.THINCLIENT_ENABLED", "false"); try { - assertThat(isThinClientEnabled()).isTrue(); + assertThat(isThinClientEnabled()).isFalse(); } finally { System.clearProperty("COSMOS.THINCLIENT_ENABLED"); } diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index 8475b83dc5ee..3571663c32ee 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -4,6 +4,7 @@ #### Features Added * Added support for N-Region synchronous commit feature - See [PR 47757](https://github.com/Azure/azure-sdk-for-java/pull/47757) +* Auto-enable thin client mode under gateway mode when the account's gateway metadata response indicates a thin client endpoint is available. Use system property `COSMOS.THINCLIENT_ENABLED=false` (or env var `COSMOS_THINCLIENT_ENABLED=false`) to opt out. No new public API is introduced. #### Breaking Changes diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java index beadb0af6cf4..74ececaf92a1 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java @@ -50,7 +50,7 @@ public class Configs { private static final String DEFAULT_THINCLIENT_ENDPOINT = ""; private static final String THINCLIENT_ENDPOINT = "COSMOS.THINCLIENT_ENDPOINT"; private static final String THINCLIENT_ENDPOINT_VARIABLE = "COSMOS_THINCLIENT_ENDPOINT"; - private static final boolean DEFAULT_THINCLIENT_ENABLED = false; + private static final boolean DEFAULT_THINCLIENT_ENABLED = true; private static final String THINCLIENT_ENABLED = "COSMOS.THINCLIENT_ENABLED"; private static final String THINCLIENT_ENABLED_VARIABLE = "COSMOS_THINCLIENT_ENABLED"; 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 192f8175978f..ccac248899d0 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 @@ -272,6 +272,7 @@ public class RxDocumentClientImpl implements AsyncDocumentClient, IAuthorization private final GlobalPartitionEndpointManagerForPerPartitionAutomaticFailover globalPartitionEndpointManagerForPerPartitionAutomaticFailover; private final RetryPolicy retryPolicy; private HttpClient reactorHttpClient; + private HttpClient thinClientReactorHttpClient; private Function httpClientInterceptor; private volatile boolean useMultipleWriteLocations; @@ -683,14 +684,7 @@ private RxDocumentClientImpl(URI serviceEndpoint, this.apiType = apiType; this.clientTelemetryConfig = clientTelemetryConfig; this.useThinClient = Configs.isThinClientEnabled() - && this.connectionPolicy.getConnectionMode() == ConnectionMode.GATEWAY - && this.connectionPolicy.getHttp2ConnectionConfig() != null - && ImplementationBridgeHelpers - .Http2ConnectionConfigHelper - .getHttp2ConnectionConfigAccessor() - .isEffectivelyEnabled( - this.connectionPolicy.getHttp2ConnectionConfig() - ); + && this.connectionPolicy.getConnectionMode() == ConnectionMode.GATEWAY; } catch (RuntimeException e) { logger.error("unexpected failure in initializing client.", e); close(); @@ -809,11 +803,19 @@ public void init(CosmosClientMetadataCachesSnapshot metadataCachesSnapshot, Func this.reactorHttpClient, this.apiType); + if (this.useThinClient) { + HttpClient thinClientHttp = thinClientHttpClient(); + if (httpClientInterceptor != null) { + thinClientHttp = httpClientInterceptor.apply(thinClientHttp); + } + this.thinClientReactorHttpClient = thinClientHttp; + } + this.thinProxy = createThinProxy(this.sessionContainer, this.consistencyLevel, this.userAgentContainer, this.globalEndpointManager, - this.reactorHttpClient); + this.useThinClient ? this.thinClientReactorHttpClient : this.reactorHttpClient); this.perPartitionFailoverConfigModifier = (databaseAccount -> { @@ -1000,6 +1002,36 @@ private HttpClient httpClient() { } } + private HttpClient thinClientHttpClient() { + // The thin client proxy communicates over HTTP/2; create a dedicated HTTP client with HTTP/2 enabled. + // If the user has already supplied an Http2ConnectionConfig with enabled=true, use it directly. + // Otherwise create a new Http2ConnectionConfig with HTTP/2 forced on, preserving any pool-size + // and stream-concurrency settings the user may have configured. + Http2ConnectionConfig userHttp2Config = this.connectionPolicy.getHttp2ConnectionConfig(); + Http2ConnectionConfig http2Config; + if (userHttp2Config != null && Boolean.TRUE.equals(userHttp2Config.isEnabled())) { + http2Config = userHttp2Config; + } else { + http2Config = new Http2ConnectionConfig().setEnabled(true); + if (userHttp2Config != null) { + http2Config + .setMaxConnectionPoolSize(userHttp2Config.getMaxConnectionPoolSize()) + .setMinConnectionPoolSize(userHttp2Config.getMinConnectionPoolSize()) + .setMaxConcurrentStreams(userHttp2Config.getMaxConcurrentStreams()); + } + } + + HttpClientConfig httpClientConfig = new HttpClientConfig(this.configs) + .withMaxIdleConnectionTimeout(this.connectionPolicy.getIdleHttpConnectionTimeout()) + .withPoolSize(this.connectionPolicy.getMaxConnectionPoolSize()) + .withProxy(this.connectionPolicy.getProxy()) + .withNetworkRequestTimeout(this.connectionPolicy.getHttpNetworkRequestTimeout()) + .withServerCertValidationDisabled(this.connectionPolicy.isServerCertValidationDisabled()) + .withHttp2ConnectionConfig(http2Config); + + return HttpClient.createFixed(httpClientConfig); + } + private void createStoreModel(boolean subscribeRntbdStatus) { // EnableReadRequestsFallback, if not explicitly set on the connection policy, // is false if the account's consistency is bounded staleness, @@ -1530,7 +1562,7 @@ private void addUserAgentSuffix(UserAgentContainer userAgentContainer, Set