Skip to content

Commit

Permalink
Fix file upload HTTP client not handling DNS changes (#3266)
Browse files Browse the repository at this point in the history
By setting the connection lease timeout to 5 minutes (defaults to infinite), HTTP operations will perform DNS lookups once every 5 minutes. This allows a client to continue performing file upload operations even if the service changes DNS due to failover
  • Loading branch information
timtay-microsoft authored Apr 13, 2023
1 parent 0d921e5 commit be0a5a5
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion iothub/device/src/Transport/Http/HttpClientHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ internal sealed class HttpClientHelper : IHttpClientHelper
private readonly ProductInfo _productInfo;
private readonly bool _isClientPrimaryTransportHandler;

// 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
private const int DefaultMaxConnectionsPerServer = 50;

// How long, in milliseconds, a given cached TCP connection created by this client's HTTP layer will live before being closed.
// If this value is set to any negative value, the connection lease will be infinite. If this value is set to 0, then the TCP connection will close after
// each HTTP request and a new TCP connection will be opened upon the next request.
//
// By closing cached TCP connections and opening a new one upon the next request, the underlying HTTP client has a chance to do a DNS lookup
// to validate that it will send the requests to the correct IP address. While it is atypical for a given IoT hub to change its IP address, it does
// happen when a given IoT hub fails over into a different region.
//
// This default value is consistent with the default value used in Azure.Core
// https://github.com/Azure/azure-sdk-for-net/blob/7e3cf643977591e9041f4c628fd4d28237398e0b/sdk/core/Azure.Core/src/Pipeline/ServicePointHelpers.cs#L29
private static readonly TimeSpan s_defaultConnectionLeaseTimeout = TimeSpan.FromMinutes(5);

public HttpClientHelper(
Uri baseAddress,
IAuthorizationProvider authenticationHeaderProvider,
Expand All @@ -59,6 +75,9 @@ 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 Down Expand Up @@ -105,6 +124,8 @@ public HttpClientHelper(
_httpClientHandler.Proxy = proxy;
}

_httpClientHandler.MaxConnectionsPerServer = DefaultMaxConnectionsPerServer;

_httpClientObj = new HttpClient(_httpClientHandler);
#endif

Expand Down Expand Up @@ -594,5 +615,5 @@ private static async Task<T> ReadAsAsync<T>(HttpContent content, CancellationTok
}

#endif
}
}
}

0 comments on commit be0a5a5

Please sign in to comment.