I have the below piece of code which I ran on .Net 4.7.2 and .Net Core but I have got different behavior for each framework
public class Program
{
private HttpClient Client = new HttpClient();
public static async Task Main(string[] args)
{
Program example = new Program();
Console.WriteLine("Starting connections");
int numberofIterations = 10;
Task<HttpResponseMessage>[] awaitableTasks = new Task<HttpResponseMessage>[numberofIterations];
for (int i = 0; i < numberofIterations; i++)
{
var httpRequestMessage = new HttpRequestMessage();
httpRequestMessage.RequestUri = new Uri("https://example.com");
httpRequestMessage.Method = new HttpMethod("GET");
awaitableTasks[i] = example.Client.SendAsync(httpRequestMessage);
//Console.WriteLine(result.StatusCode);
}
Console.WriteLine("Connections done");
await Task.WhenAll(awaitableTasks);
}
}
With the .Net Core framework, the network traces shows a separate tcp connection for each request while with the.NEt 4.7.2 framework the sockets get reused.
Network Trace .Net Core
Network Trace .Net 4.7.2
Appreciate your thoughts to understand the differences, to explain this behavior and the best way to overcome this issue.
2
Answers
Short Answer, the below modification to the code will force my .net core app to not create more than two sockets and reuse them.
Updated Answer
More Details:
The .Net Framework 4.x.x HttpClient implementation is built on top of HttpWebRequest and ServicePoint which can be managed by the ServicePointManager. The ServicePointManager has a default connection limit set to 10 for ASP.NET hosted applications and 2 for all others, and that is why in my above example the 2 sockets were opened and reused as the application were prevented to create more than 2 connections(sockets) per service point.
See the references below for a bit more understanding
https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.defaultconnectionlimit?view=net-6.0#system-net-servicepointmanager-defaultconnectionlimit
https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepoint?view=net-6.0
C# Does Each Instance of HttpClient Get it's Own ServicePoint
In .Net Core, the implementation has been changed multiple times, no longer managed by the ServicePointManager and has no default connection limit. The below article has the full story of the HttpClient Class.
https://www.stevejgordon.co.uk/httpclient-connection-pooling-in-dotnet-core
Thanks to @user700390 and @PanagiotisKanavos and @JeremyLakeman for their help and guidance toward getting the answer to this question.
Have you seen this resource:
Using HttpClientFactory without dependency injection
More detailed information found in https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#alternatives-to-ihttpclientfactory-2
Also possibly relevant (but more focused on DI):
Use IHttpClientFactory to implement resilient HTTP requests
Here are a few relevant excerpts:
….
HttpClient lifetimes