问题
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?
回答1:
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.
回答2:
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 useBaseAdress
. From point 1) I need to use new HttpClient instance per uniqueBaseAdress
(host).But what if I use
HttpClient
for requests to multiple hosts withoutBaseAdress
by absolute address? You can chase the calls fromHttpClient
toSocketsHttpHanlder
toHttpConnectionPoolManager
(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 singleHttpClient
instance for multiple hosts withoutBaseAdress
usage.
来源:https://stackoverflow.com/questions/29976944/httpclient-instancing-per-service-endpoint