What is the overhead of creating a new HttpClient per call in a WebAPI client?

Bruno Pessanha picture Bruno Pessanha · Mar 21, 2014 · Viewed 69.2k times · Source

What should be the HttpClient lifetime of a WebAPI client?
Is it better to have one instance of the HttpClient for multiple calls?

What's the overhead of creating and disposing a HttpClient per request, like in example below (taken from http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client):

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:9000/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // New code:
    HttpResponseMessage response = await client.GetAsync("api/products/1");
    if (response.IsSuccessStatusCode)
    {
        Product product = await response.Content.ReadAsAsync<Product>();
        Console.WriteLine("{0}\t${1}\t{2}", product.Name, product.Price, product.Category);
    }
}

Answer

Darrel Miller picture Darrel Miller · Mar 21, 2014

HttpClient has been designed to be re-used for multiple calls. Even across multiple threads. The HttpClientHandler has Credentials and Cookies that are intended to be re-used across calls. Having a new HttpClient instance requires re-setting up all of that stuff. Also, the DefaultRequestHeaders property contains properties that are intended for multiple calls. Having to reset those values on each request defeats the point.

Another major benefit of HttpClient is the ability to add HttpMessageHandlers into the request/response pipeline to apply cross cutting concerns. These could be for logging, auditing, throttling, redirect handling, offline handling, capturing metrics. All sorts of different things. If a new HttpClient is created on each request, then all of these message handlers need to be setup on each request and somehow any application level state that is shared between requests for these handlers also needs to be provided.

The more you use the features of HttpClient, the more you will see that reusing an existing instance makes sense.

However, the biggest issue, in my opinion is that when a HttpClient class is disposed, it disposes HttpClientHandler, which then forcibly closes the TCP/IP connection in the pool of connections that is managed by ServicePointManager. This means that each request with a new HttpClient requires re-establishing a new TCP/IP connection.

From my tests, using plain HTTP on a LAN, the performance hit is fairly negligible. I suspect this is because there is an underlying TCP keepalive that is holding the connection open even when HttpClientHandler tries to close it.

On requests that go over the internet, I have seen a different story. I have seen a 40% performance hit due to having to re-open the request every time.

I suspect the hit on a HTTPS connection would be even worse.

My advice is to keep an instance of HttpClient for the lifetime of your application for each distinct API that you connect to.