When instancing an HttpClient, the one common piece of advice is:
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":
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?
NET documentation for HttpClient: HttpClient is intended to be instantiated once and re-used throughout the life of an application.
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.
The correct way as per the post is to create a single instance of HttpClient as it helps to reduce waste of sockets.
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.
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.
I faced with the same question too.
And there are results of my investigation:
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With