Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpClient Instancing Per Service-Endpoint

When instancing an HttpClient, the one common piece of advice is:

  • Use a singleton, do not dispose after each use.

However, based on this link I see commentary which I think implies another rule:

The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.

This makes me wonder if I am supposed to create one HttpClient instance for each service-endpoint I interact with. By "service-endpoint", I mean a distinct base address. Each of the following would be a distinct "service-endpoint":

  • "http://foo.net/api/Message/"
  • "http://bar.com/api/Message/"
  • "http://wow.gov/api/Message/"
  • "http://now.com/api/Message/"
  • "http://mom.org/api/Message/"
  • "http://dog.com/api/Message/"

Certainly if I intend on using the "BaseAddress" property of the HttpClient, and if I'm dealing with concurrent calls, then I will need to have one instance of HttpClient per "service-endpoint".

However, HttpClient does allow me to specify an absolute address explicitly:

HttpClient client = new HttpClient(...);

client.PostAsJsonAsync("http://foo.net/api/Message/", ...);
client.PostAsJsonAsync("http://bar.com/api/Message/", ...);
client.PostAsJsonAsync("http://wow.gov/api/Message/", ...);
client.PostAsJsonAsync("http://now.com/api/Message/", ...);
client.PostAsJsonAsync("http://mom.org/api/Message/", ...);
client.PostAsJsonAsync("http://dog.com/api/Message/", ...);

The above code works, and it is exactly what I want for the current application I'm building. But the nagging question remains...am I doing something wrong if I use one HttpClient for all service-endpoints my application communicates with?

Is there a reason why I would truly need the "connection pool isolation" that was mentioned in the above quotation?

like image 684
Brent Arias Avatar asked Apr 30 '15 20:04

Brent Arias


People also ask

Can HttpClient be reused?

NET documentation for HttpClient: HttpClient is intended to be instantiated once and re-used throughout the life of an application.

Does HttpClient need to be disposed C#?

There is no need to dispose of the HttpClient instances from HttpClientFactory. Disposal will not actually do anything in this case because the factory manages the handler and connection lifetimes and not the HttpClient instances.

Should we create a new single instance of HttpClient for all requests?

The correct way as per the post is to create a single instance of HttpClient as it helps to reduce waste of sockets.

What are the differences between HttpClientFactory and HttpClient?

It has a method CreateClient which returns the HttpClient Object. But in reality, HttpClient is just a wrapper, for HttpMessageHandler. HttpClientFactory manages the lifetime of HttpMessageHandelr, which is actually a HttpClientHandler who does the real work under the hood.


2 Answers

But I want to know if I will be compromising the inner workings of HttpClient because I'm making many endpoints share the same connection pool.

No, I don't think a single instance of HttpClient will exhaust your resources, but that really depends on how many concurrent requests you'll be making. HttpClient is designed to serve concurrent requests, and by using asynchronous API's such (XXXAsync), you can achieve just that.

I would advise not to forget to set ServicePointManager.DefaultConnectionLimit to a higher number, as it's default value is 2 (concurrent requests).

Also, If you think you'll be hitting the wall quickly with a single instance, I'd suggest as always to profile your application to understand the exact bottleneck.

like image 174
Yuval Itzchakov Avatar answered Oct 10 '22 11:10

Yuval Itzchakov


I faced with the same question too.

And there are results of my investigation:

  1. Use separate instances of HttpClient just if you need to change its non thread-safely settings (DefaultRequestHeaders, BaseAddress) during requests. It would be useful and safely to create separate instances with set of those specific settings for each instance. Some more details: HttpClient–Is It Really Thread-Safe?

  2. Ok, I create specific instance of HttpClient, but I wan't to use BaseAdress. From point 1) I need to use new HttpClient instance per unique BaseAdress (host).

    But what if I use HttpClient for requests to multiple hosts without BaseAdress by absolute address? You can chase the calls from HttpClient to SocketsHttpHanlder to HttpConnectionPoolManager (dotnet source code) and see it creates separate 'HttpConnectionPool' for each host and add the pool to 'ConcurrentDictionary' _pools. That means we have separate pool for each unique host anyway. That's why I prefer to use single HttpClient instance for multiple hosts without BaseAdress usage.

like image 38
Klyuch Avatar answered Oct 10 '22 10:10

Klyuch