Skip to content

Commit

Permalink
Set connection expiration timeouts (#19524)
Browse files Browse the repository at this point in the history
  • Loading branch information
pakrym authored Mar 17, 2021
1 parent 37a6b66 commit 0a74e5a
Show file tree
Hide file tree
Showing 8 changed files with 662 additions and 13 deletions.
6 changes: 6 additions & 0 deletions sdk/core/Azure.Core/Azure.Core.sln
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Core.Spatia
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Perf", "perf\Azure.Core.Perf.csproj", "{B6D7909F-4DE6-4895-BF39-EF892BA64BA3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Test.Perf", "..\..\..\common\Perf\Azure.Test.Perf\Azure.Test.Perf.csproj", "{33A10110-D88A-459B-82C1-FECEF86A822A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -81,6 +83,10 @@ Global
{B6D7909F-4DE6-4895-BF39-EF892BA64BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6D7909F-4DE6-4895-BF39-EF892BA64BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6D7909F-4DE6-4895-BF39-EF892BA64BA3}.Release|Any CPU.Build.0 = Release|Any CPU
{33A10110-D88A-459B-82C1-FECEF86A822A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33A10110-D88A-459B-82C1-FECEF86A822A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33A10110-D88A-459B-82C1-FECEF86A822A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33A10110-D88A-459B-82C1-FECEF86A822A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions sdk/core/Azure.Core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Check the `JsonIgnoreAttribute.Condition` property added in .NET 5 when discovering members with `JsonObjectSerializer`.
- `ETag` now returns `string.Empty` if it is constructed with a null value.
- Keep-Alive connections are recycled every 300 seconds to observe DNS changes.

## 1.10.0 (2021-03-09)

Expand Down
598 changes: 598 additions & 0 deletions sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion sdk/core/Azure.Core/src/Azure.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
<Version>1.11.0-beta.1</Version>
<!--The ApiCompatVersion is managed automatically and should not generally be modified manually.-->
<ApiCompatVersion>1.10.0</ApiCompatVersion>
<!-- TODO: remove when we have a released package with the netcoreapp2.1 target -->
<ApiCompatVersion Condition="$(TargetFramework) == 'netcoreapp2.1'"></ApiCompatVersion>
<PackageTags>Microsoft Azure Client Pipeline</PackageTags>
<Nullable>enable</Nullable>
<DefineConstants>$(DefineConstants);AZURE_NULLABLE</DefineConstants>
<TargetFrameworks>$(RequiredTargetFrameworks);net461;net5.0</TargetFrameworks>
<TargetFrameworks>$(RequiredTargetFrameworks);net461;netcoreapp2.1;net5.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableClientSdkAnalyzers>true</EnableClientSdkAnalyzers>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class AzureBaseBuffersExtensions
public static async Task WriteAsync(this Stream stream, ReadOnlyMemory<byte> buffer, CancellationToken cancellation = default)
{
Argument.AssertNotNull(stream, nameof(stream));
#if NET5_0
#if NETCOREAPP
await stream.WriteAsync(buffer, cancellation).ConfigureAwait(false);
#else

Expand Down Expand Up @@ -58,7 +58,7 @@ public static async Task WriteAsync(this Stream stream, ReadOnlySequence<byte> b
{
foreach (ReadOnlyMemory<byte> segment in buffer)
{
#if NET5_0
#if NETCOREAPP
await stream.WriteAsync(segment, cancellation).ConfigureAwait(false);
#else
if (MemoryMarshal.TryGetArray(segment, out ArraySegment<byte> arraySegment))
Expand Down
15 changes: 9 additions & 6 deletions sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,20 @@ private async ValueTask ProcessAsync(HttpMessage message, bool async)

private static HttpClient CreateDefaultClient()
{
var httpClientHandler = new HttpClientHandler();
#if NETFRAMEWORK || NETSTANDARD
HttpClientHandler httpMessageHandler = new HttpClientHandler();
#else

SocketsHttpHandler httpMessageHandler = new SocketsHttpHandler();
#endif
if (HttpEnvironmentProxy.TryCreate(out IWebProxy webProxy))
{
httpClientHandler.Proxy = webProxy;
httpMessageHandler.Proxy = webProxy;
}

#if NETFRAMEWORK
ServicePointHelpers.SetLimits(httpClientHandler);
#endif
ServicePointHelpers.SetLimits(httpMessageHandler);

return new HttpClient(httpClientHandler)
return new HttpClient(httpMessageHandler)
{
// Timeouts are handled by the pipeline
Timeout = Timeout.InfiniteTimeSpan
Expand Down
45 changes: 42 additions & 3 deletions sdk/core/Azure.Core/src/Pipeline/ServicePointHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Net;
using System.Net.Http;
using System.Threading;

namespace Azure.Core.Pipeline
{
// This type manages changing HttpClient/HttpWebRequest defaults to more appropriate values
// There are two limits we target:
// - Per Server Connection Limit
// - Keep Alive Connection Timeout
// On .NET Core 2.1 & NET 5.0 the HttpClientTransport would default to using the SocketClientHandler
// we adjust both limits on the client handler
// On .NET Standard & NET 4.6+ the HttpClientTransport would default to using the HttpClientHandler
// and there is no easy way to set Keep Alive Connection Timeout but it's mitigated by WebHttpRequestTransport
// being the default on NET 4.6.1
// The default transport on NET 4.6.1 is WebHttpRequestTransport the default and we are updating both
// limits on the service point

internal static class ServicePointHelpers
{
private const int RuntimeDefaultConnectionLimit = 2;
private const int IncreasedConnectionLimit = 50;
private const int IncreasedConnectionLeaseTimeout = 300 * 1000;

#if NETFRAMEWORK || NETSTANDARD
private const int DefaultConnectionLeaseTimeout = Timeout.Infinite;

public static void SetLimits(ServicePoint requestServicePoint)
{
Expand All @@ -18,15 +36,36 @@ public static void SetLimits(ServicePoint requestServicePoint)
{
requestServicePoint.ConnectionLimit = IncreasedConnectionLimit;
}

if (requestServicePoint.ConnectionLeaseTimeout == DefaultConnectionLeaseTimeout)
{
requestServicePoint.ConnectionLeaseTimeout = IncreasedConnectionLeaseTimeout;
}
}

public static void SetLimits(HttpClientHandler requestServicePoint)
public static void SetLimits(HttpClientHandler httpClientHandler)
{
// Only change when the default runtime limit is used
if (requestServicePoint.MaxConnectionsPerServer == RuntimeDefaultConnectionLimit)
if (httpClientHandler.MaxConnectionsPerServer == RuntimeDefaultConnectionLimit)
{
httpClientHandler.MaxConnectionsPerServer = IncreasedConnectionLimit;
}
}
#else // NETCOREAPP +
private static TimeSpan DefaultConnectionLeaseTimeoutTimeSpan = Timeout.InfiniteTimeSpan;
private static TimeSpan IncreasedConnectionLeaseTimeoutTimeSpan = TimeSpan.FromMilliseconds(IncreasedConnectionLeaseTimeout);

public static void SetLimits(SocketsHttpHandler socketsHttpHandler)
{
if (socketsHttpHandler.MaxConnectionsPerServer == RuntimeDefaultConnectionLimit)
{
socketsHttpHandler.MaxConnectionsPerServer = IncreasedConnectionLimit;
}
if (socketsHttpHandler.PooledConnectionLifetime == DefaultConnectionLeaseTimeoutTimeSpan)
{
requestServicePoint.MaxConnectionsPerServer = IncreasedConnectionLimit;
socketsHttpHandler.PooledConnectionLifetime = IncreasedConnectionLeaseTimeoutTimeSpan;
}
}
#endif
}
}
2 changes: 1 addition & 1 deletion sdk/core/Azure.Core/src/Shared/NullableAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#pragma warning disable SA1402 // File may only contain a single type
#pragma warning disable SA1649 // File name should match first type name

#if !NETCOREAPP
#if !NET5_0
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
Expand Down

0 comments on commit 0a74e5a

Please sign in to comment.