Skip to content

Commit

Permalink
Properly set connection lease timeout regardless of .NET target frame…
Browse files Browse the repository at this point in the history
…work (#3279)

Previous fix only worked for .NET framework, not .NET core

#3263
  • Loading branch information
timtay-microsoft authored Apr 18, 2023
1 parent be0a5a5 commit 6027e88
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 8 deletions.
11 changes: 3 additions & 8 deletions iothub/device/src/Transport/Http/HttpClientHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@ public HttpClientHelper(
_authenticationHeaderProvider = authenticationHeaderProvider;
_defaultErrorMapping = new ReadOnlyDictionary<HttpStatusCode, Func<HttpResponseMessage, Task<Exception>>>(defaultErrorMapping);

ServicePoint servicePoint = ServicePointManager.FindServicePoint(_baseAddress);
servicePoint.ConnectionLeaseTimeout = s_defaultConnectionLeaseTimeout.Milliseconds;

#if NET451
TlsVersions.Instance.SetLegacyAcceptableVersions();

Expand All @@ -104,8 +101,6 @@ public HttpClientHelper(
_httpClientHandler.UseProxy = (proxy != null);
_httpClientHandler.Proxy = proxy;
}

_httpClientObj = _httpClientHandler != null ? new HttpClient(_httpClientHandler) : new HttpClient();
#else

_httpClientHandler = httpClientHandler ?? new HttpClientHandler();
Expand All @@ -123,11 +118,11 @@ public HttpClientHelper(
_httpClientHandler.UseProxy = proxy != null;
_httpClientHandler.Proxy = proxy;
}
#endif

_httpClientHandler.MaxConnectionsPerServer = DefaultMaxConnectionsPerServer;
ServicePointHelpers.SetLimits(_httpClientHandler, _baseAddress);

_httpClientObj = new HttpClient(_httpClientHandler);
#endif
_httpClientObj = _httpClientHandler != null ? new HttpClient(_httpClientHandler) : new HttpClient();

_httpClientObj.BaseAddress = _baseAddress;
_httpClientObj.Timeout = timeout;
Expand Down
54 changes: 54 additions & 0 deletions iothub/device/src/Transport/Http/ServicePointHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

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

namespace Microsoft.Azure.Devices.Client
{
// This type manages changing HttpClient defaults to more appropriate values
// There are two limits we target:
// - Per Server Connection Limit
// - Keep Alive Connection Timeout
// On .NET Core 2.1+ the HttpClient defaults to using the HttpSocketHandler so we adjust both limits on the client handler
//
// On .NET Standard & NET 4.51+ the HttpClient defaults to using the HttpClientHandler
// and there is no easy way to set Keep Alive Connection Timeout but it's mitigated by setting the service point's connection lease timeout
internal static class ServicePointHelpers
{
// These default values are consistent with Azure.Core default values:
// https://github.com/Azure/azure-sdk-for-net/blob/7e3cf643977591e9041f4c628fd4d28237398e0b/sdk/core/Azure.Core/src/Pipeline/ServicePointHelpers.cs#L28
internal const int DefaultMaxConnectionsPerServer = 50;

internal const int DefaultConnectionLeaseTimeout = 300 * 1000; // 5 minutes

// messageHandler passed in is an HttpClientHandler for .NET Framework and .NET standard, and a SocketsHttpHandler for .NET core
public static void SetLimits(HttpMessageHandler messageHandler, Uri baseUri, int connectionLeaseTimeoutMilliseconds = DefaultConnectionLeaseTimeout)
{
if (messageHandler == null)
{
// no limits can be set if no handler is provided
return;
}

switch (messageHandler)
{
case HttpClientHandler httpClientHandler:
#if !NET451
httpClientHandler.MaxConnectionsPerServer = DefaultMaxConnectionsPerServer;
#endif
ServicePoint servicePoint = ServicePointManager.FindServicePoint(baseUri);
servicePoint.ConnectionLeaseTimeout = connectionLeaseTimeoutMilliseconds;
break;
#if NETCOREAPP2_1_OR_GREATER || NET5_0_OR_GREATER
// SocketsHttpHandler is only available in netcore2.1 and onwards
case SocketsHttpHandler socketsHttpHandler:
socketsHttpHandler.MaxConnectionsPerServer = DefaultMaxConnectionsPerServer;
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMilliseconds(connectionLeaseTimeoutMilliseconds);
break;
#endif
}
}
}
}

0 comments on commit 6027e88

Please sign in to comment.