Skip to content

Commit

Permalink
Add PortReuseMode to CosmosClientOptions (#1000)
Browse files Browse the repository at this point in the history
* add PortReuseMode

* update changelog, update baseline, and add VerifyPortReuseModeIsSyncedWithDirect test

* add see also links to ReuseUnicastPort

* add remarks to PortReuseMode

* fix changelog
  • Loading branch information
ausfeldt authored and kirankumarkolli committed Nov 20, 2019
1 parent 7ae5c61 commit 101679f
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 263 deletions.
12 changes: 12 additions & 0 deletions Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,18 @@ public int? MaxTcpConnectionsPerEndpoint
set;
}

/// <summary>
/// (Direct/TCP) Controls the client port reuse policy used by the transport stack.
/// </summary>
/// <value>
/// The default value is PortReuseMode.ReuseUnicastPort.
/// </value>
public PortReuseMode? PortReuseMode
{
get;
set;
}

/// <summary>
/// (Direct/TCP) This is an advanced setting that controls the number of TCP connections that will be opened eagerly to each Cosmos DB back-end.
/// </summary>
Expand Down
29 changes: 28 additions & 1 deletion Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class CosmosClientOptions
private TimeSpan? openTcpConnectionTimeout;
private int? maxRequestsPerTcpConnection;
private int? maxTcpConnectionsPerEndpoint;
private PortReuseMode? portReuseMode;
private IWebProxy webProxy;

/// <summary>
Expand Down Expand Up @@ -274,6 +275,27 @@ public int? MaxTcpConnectionsPerEndpoint
}
}

/// <summary>
/// (Direct/TCP) Controls the client port reuse policy used by the transport stack.
/// </summary>
/// <value>
/// The default value is PortReuseMode.ReuseUnicastPort.
/// </value>
/// <remarks>
/// ReuseUnicastPort and PrivatePortPool are not mutually exclusive.
/// When PrivatePortPool is enabled, the client first tries to reuse a port it already has.
/// It falls back to allocating a new port if the initial attempts failed. If this fails, too, the client then falls back to ReuseUnicastPort.
/// </remarks>
public PortReuseMode? PortReuseMode
{
get => this.portReuseMode;
set
{
this.portReuseMode = value;
this.ValidateDirectTCPSettings();
}
}

/// <summary>
/// (Gateway/Https) Get or set the proxy information used for web requests.
/// </summary>
Expand Down Expand Up @@ -522,7 +544,8 @@ internal ConnectionPolicy GetConnectionPolicy()
OpenTcpConnectionTimeout = this.OpenTcpConnectionTimeout,
MaxRequestsPerTcpConnection = this.MaxRequestsPerTcpConnection,
MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint,
EnableEndpointDiscovery = !this.LimitToEndpoint
EnableEndpointDiscovery = !this.LimitToEndpoint,
PortReuseMode = this.portReuseMode
};

if (this.ApplicationRegion != null)
Expand Down Expand Up @@ -650,6 +673,10 @@ private void ValidateDirectTCPSettings()
{
settingName = nameof(this.MaxTcpConnectionsPerEndpoint);
}
else if (this.PortReuseMode.HasValue)
{
settingName = nameof(this.PortReuseMode);
}
}

if (!string.IsNullOrEmpty(settingName))
Expand Down
537 changes: 278 additions & 259 deletions Microsoft.Azure.Cosmos/src/DocumentClient.cs

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ public CosmosClientBuilder WithConnectionModeDirect()
/// Together with MaxRequestsPerTcpConnection, this setting limits the number of requests that are simultaneously sent to a single Cosmos DB back-end(MaxRequestsPerTcpConnection x MaxTcpConnectionPerEndpoint).
/// The default value is 65,535. Value must be greater than or equal to 16.
/// </param>
/// <param name="portReuseMode">
/// (Direct/TCP) Controls the client port reuse policy used by the transport stack.
/// The default value is PortReuseMode.ReuseUnicastPort.
/// </param>
/// <remarks>
/// For more information, see <see href="https://docs.microsoft.com/azure/documentdb/documentdb-performance-tips#direct-connection">Connection policy: Use direct connection mode</see>.
/// </remarks>
Expand All @@ -238,12 +242,14 @@ public CosmosClientBuilder WithConnectionModeDirect()
internal CosmosClientBuilder WithConnectionModeDirect(TimeSpan? idleTcpConnectionTimeout = null,
TimeSpan? openTcpConnectionTimeout = null,
int? maxRequestsPerTcpConnection = null,
int? maxTcpConnectionsPerEndpoint = null)
int? maxTcpConnectionsPerEndpoint = null,
Cosmos.PortReuseMode? portReuseMode = null)
{
this.clientOptions.IdleTcpConnectionTimeout = idleTcpConnectionTimeout;
this.clientOptions.OpenTcpConnectionTimeout = openTcpConnectionTimeout;
this.clientOptions.MaxRequestsPerTcpConnection = maxRequestsPerTcpConnection;
this.clientOptions.MaxTcpConnectionsPerEndpoint = maxTcpConnectionsPerEndpoint;
this.clientOptions.PortReuseMode = portReuseMode;

this.clientOptions.ConnectionMode = ConnectionMode.Direct;
this.clientOptions.ConnectionProtocol = Protocol.Tcp;
Expand Down
28 changes: 28 additions & 0 deletions Microsoft.Azure.Cosmos/src/PortReuseMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
/// <summary>
/// Port reuse policy options used by the transport stack
/// </summary>
public enum PortReuseMode
{
/// <summary>
/// Windows Server 2016 and newer: Uses the SO_REUSE_UNICASTPORT option if the operating system has automatic client port reuse enabled.
/// Older versions of Windows, Linux, other: Uses default socket options.
/// </summary>
/// <remarks>
/// see also
/// https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
/// https://docs.microsoft.com/en-us/powershell/module/nettcpip/set-nettcpsetting?view=win10-ps
/// https://support.microsoft.com/en-us/help/3149157/reliability-and-scalability-improvements-in-tcp-ip-for-windows-8-1-and
/// </remarks>
ReuseUnicastPort = 0,
/// <summary>
/// Windows: Tracks client ports used by the Cosmos DB client and reuses them. Ports are reused at DocumentClient scope.
/// Linux: Uses default socket options.
/// </summary>
PrivatePortPool = 1,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Tests
{
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using Microsoft.Azure.Cosmos.Client.Core.Tests;
Expand Down Expand Up @@ -44,6 +45,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated()
TimeSpan openTcpConnectionTimeout = new TimeSpan(0, 0, 5);
int maxRequestsPerTcpConnection = 30;
int maxTcpConnectionsPerEndpoint = 65535;
Cosmos.PortReuseMode portReuseMode = Cosmos.PortReuseMode.PrivatePortPool;
IWebProxy webProxy = new TestWebProxy();

CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder(
Expand Down Expand Up @@ -131,7 +133,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated()
idleTcpConnectionTimeout,
openTcpConnectionTimeout,
maxRequestsPerTcpConnection,
maxTcpConnectionsPerEndpoint
maxTcpConnectionsPerEndpoint,
portReuseMode
);

cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient());
Expand All @@ -142,13 +145,29 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated()
Assert.AreEqual(openTcpConnectionTimeout, clientOptions.OpenTcpConnectionTimeout);
Assert.AreEqual(maxRequestsPerTcpConnection, clientOptions.MaxRequestsPerTcpConnection);
Assert.AreEqual(maxTcpConnectionsPerEndpoint, clientOptions.MaxTcpConnectionsPerEndpoint);
Assert.AreEqual(portReuseMode, clientOptions.PortReuseMode);

//Verify GetConnectionPolicy returns the correct values
policy = clientOptions.GetConnectionPolicy();
Assert.AreEqual(idleTcpConnectionTimeout, policy.IdleTcpConnectionTimeout);
Assert.AreEqual(openTcpConnectionTimeout, policy.OpenTcpConnectionTimeout);
Assert.AreEqual(maxRequestsPerTcpConnection, policy.MaxRequestsPerTcpConnection);
Assert.AreEqual(maxTcpConnectionsPerEndpoint, policy.MaxTcpConnectionsPerEndpoint);
Assert.AreEqual(portReuseMode, policy.PortReuseMode);
}

[TestMethod]
public void VerifyPortReuseModeIsSyncedWithDirect()
{
CollectionAssert.AreEqual(
Enum.GetNames(typeof(PortReuseMode)).OrderBy(x => x).ToArray(),
Enum.GetNames(typeof(Cosmos.PortReuseMode)).OrderBy(x => x).ToArray()
);

CollectionAssert.AreEqual(
Enum.GetValues(typeof(PortReuseMode)).Cast<int>().ToArray(),
Enum.GetValues(typeof(Cosmos.PortReuseMode)).Cast<int>().ToArray()
);
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,16 @@
],
"MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.ConsistencyLevel] get_ConsistencyLevel()"
},
"System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode] get_PortReuseMode()": {
"Type": "Method",
"Attributes": [],
"MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode] get_PortReuseMode()"
},
"System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode] PortReuseMode": {
"Type": "Property",
"Attributes": [],
"MethodInfo": null
},
"System.Nullable`1[System.Int32] get_MaxRequestsPerTcpConnection()": {
"Type": "Method",
"Attributes": [],
Expand Down Expand Up @@ -1530,6 +1540,11 @@
"Attributes": [],
"MethodInfo": "Void set_OpenTcpConnectionTimeout(System.Nullable`1[System.TimeSpan])"
},
"Void set_PortReuseMode(System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode])": {
"Type": "Method",
"Attributes": [],
"MethodInfo": "Void set_PortReuseMode(System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode])"
},
"Void set_RequestTimeout(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
Expand Down Expand Up @@ -3737,6 +3752,27 @@
},
"NestedTypes": {}
},
"PortReuseMode": {
"Subclasses": {},
"Members": {
"Int32 value__": {
"Type": "Field",
"Attributes": [],
"MethodInfo": null
},
"Microsoft.Azure.Cosmos.PortReuseMode PrivatePortPool": {
"Type": "Field",
"Attributes": [],
"MethodInfo": null
},
"Microsoft.Azure.Cosmos.PortReuseMode ReuseUnicastPort": {
"Type": "Field",
"Attributes": [],
"MethodInfo": null
}
},
"NestedTypes": {}
},
"QueryDefinition": {
"Subclasses": {},
"Members": {
Expand Down
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- [#995](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/995) Included session token in diagnostics
- [#995](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/995) Included session token in diagnostics.
- [#1000](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/1000) Add PortReuseMode to CosmosClientOptions.

### Fixed

Expand Down

0 comments on commit 101679f

Please sign in to comment.