Understanding HttpClient Best Practice

We use httpclient widely in the application to make connections to another external API to get data from c# code.

But it is required to see what impact is if we use this HTTP client in a bad way. There will be performance issues in the application if we use the below way.

Consider the code below C# code.

Console.WriteLine("Starting connections");
for (int i = 0; i < 100; i++)
{
    using (var client = new HttpClient())
    {
        var result = await client.GetAsync("http://google.com");
        Console.WriteLine(result.StatusCode);
    }
}

Output like below.

Output

We can use statements for classes that implement IDisposable.

In this case, HttpClient goes out of scope and is disposed of. The disposal method is called, and whatever resources are in use are cleaned up. This is a very typical pattern in .NET, and we use it for everything from database connections to streamwriters.

All unmanaged code will be cleaned once the block is out of scope.

But with HttpClient, the case is different and has some problems here.

Problems

Here, we are creating httpclient object multiple times, which causes a problem called.

Socket exhaustion problems

This means when the HTTP client makes a connection to the url mentioned, the socket remains open even when the HTTP connection gets closed. This problem does not always happen, but it may happen when we create httpclient objects frequently in applications.

It is ideal to reuse a singleton object of an HTTP client and reuse it.

Therefore, HttpClient is intended to be instantiated once and reused throughout the life of an application.

In the screenshot below, I have used netstat.exe to investigate.

Investigate

All TIME_WAIT state, which means that the connection has been closed on one side (ours i.e. .NET code side), but we’re still waiting to see if any additional packets come in on it because they might have been delayed on the network somewhere.

There is a limit to how quickly Windows can open new sockets, so if you exhaust the connection pool, then you’re likely to see errors like this.

System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.

TCP states diagram

TCP

Solution

  1. Make httpclient singleton so that this will be reusable each and every time.
  2. We can make httpclient static.
  3. We can use IHttpClientFactory.

I will create another article on IHttpClientFactory.

The fix Code below is the solution.

Console.WriteLine("Starting connections");
private static HttpClient Client = new HttpClient();
for (int i = 0; i < 10; i++)
{
    var result = await Client.GetAsync("http://aspnetmonsters.com");
    Console.WriteLine(result.StatusCode);
}
Console.WriteLine("Connections done");
Console.ReadLine();

Understanding the above code.

  1. We have created a global object for httpclient
  2. We have not used using block for HTTP clients, please try to avoid it.

Conclusion

Using block for HTTP clients may create huge (even if it implemented IDisposable Interface ) problems in production and can degrade server performance and result in slow server responses.