I am creating a new Asp.Net Core (net standard 2) Mvc controller that uses a WebAPI (REST) call to obtain the data. I was following many of the examples shown all over the Interweb from both microsoft and non-microsoft sources. These all use the "standard" using(var client = new HttpClient()) construct.
However, then read the documentation for HttpClient
HttpClient is intended to be instantiated once and re-used throughout
the life of an application. Instantiating an HttpClient class for
every request will exhaust the number of sockets available under heavy
loads. This will result in SocketException errors. Below is an example
using HttpClient correctly.
This got me thinking, do I create a scoped instance and add it to DI, or follow their example on the same page, and create a static instance on the controller? If a static instance, how do I dispose it?
Alternately, can anyone point me to a production ready MVC wrapper for a standard CRUD view implementation?
If you have not read "You're using HttpClient wrong and it is destabilizing your software".
If you have any kind of load at all you need to remember these two
things:
Make your HttpClient static.
Do not dispose of or wrap your HttpClient in a using unless you explicitly are looking for a particular behavior (such as causing your services to fail).
I agree with mike z DI can be used in this case.
e.g. SimpleInjector's Singleton is taking care of disposing.
Simple Injector guarantees that instances are disposed in opposite
order of creation.
If you still want to wrap it, look at "Generic wrapper for calling ASP.NET WEB API REST service using HttpClient with optional HMAC authentication"
Upd:
Make sure you dispose of instances of both of HttpRequestMessage and HttpResponseMessage. See example of usage
Source: http://faithlife.codes/blog/2017/03/usage-guidelines-for-httpclient/
For anyone using .net core 2.1 or greater it is recommended to use HttpClientFactory
To address those mentioned issues and make the management of HttpClient instances easier, .NET Core 2.1 introduced a new HttpClientFactory that can also be used to implement resilient HTTP calls
See microsoft docs on how it can be leveraged.
Related
When diposing an HttpClient, one can run into the "socket exhaustion" problem. So the standard advice is to reuse the client whenever possible.
So I was surprised to find the official Blazor templates (dotnet new blazorwasm) have this scoped factory in Program.cs:
builder.Services.AddScoped(sp =>
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
I'm even using the IDisposableAnalyzers analyser library that specifically checks for such things, and it warns to replace that line with a single instance.
Why is the template written that way?
This is what I've found.
It has long been recommended to reuse an HttpClient, due to the socket exhaustion problem.
But Blazor's HttpClient doesn't use TCP for connections, it uses the browser's Fetch API instead. And the Fetch API, according to MDN is JavaScript-based:
The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline, such as requests and responses. It also provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.
So the original problem doesn't exist, which means we can safely use as many HttpClient instances as we want.
Which is why the Blazor templates use a factory to create multiple instances.
TL;DR: it should be safe.
My only concern is that the above is based on the Blazor docs, but the framework docs for HttpClient do not mention this special behaviour for Blazor. (I wonder how this works - maybe the Blazor SDK has a different implementation for HttpClient than the server SDK?)
If my analysis is wrong, please let me know.
I've got a .Net Core project that needs to connect to around 4 different API services, I'm no expert with any of the HttpClient code, but from what I found, was that you'd generally only want to reuse one instance of your HttpClient. From what I can tell the general consensus is to use the HttpClientFactory in .Net Core by registering it in your Startup class and then requesting it using DI.
Now most of my default headers and such are all generally the same besides the BaseAddress url, how should I go about this when connecting to 4 diff API services? Should I register 4 different named clients or have one client with all the default information pre-set and then manually configure it as needed e.g. configuring the address?
General questions would be as I'm fairly new to this is, it's been said to re-use one instance of an HttpClient.
If I create 4 different named clients for each API service, wouldn't this create 4 instances of the HttpClient when I call the .CreateClient() method?
The .CreateClient() creates a new instance every time it's called, doesn't this defeat the purpose of having one instance of the HttpClient if say I need to make 3 different calls to one API service, each of those calls will call a .CreateClient() to establish some sort of connection and that will create 3 instances of the HttpClient?
Any help for clarity would be appreciated,
Thanks!
The purpose of using IHttpClientFactory is not to reuse instances of HttpClient. Instead, it is to reuse (by pooling) instances of HttpMessageHandler (actually HttpClientHandler, which is derived from the abstract HttpMessageHandler) that is the underlying object that manages HTTP connections & sockets. This diagram from Microsoft Docs shows it well.
You were worried that frequent calls to IHttpClientFactory.CreateClient() will create the same problem as frequent calls to new HttpClient(). However, this is not the case. As explained by Microsoft docs, the reason that frequent calls to new HttpClient() will result in socket exhaustion is that this constructor will create a new instance of HttpMessageHandler:
However, the issue isn't really with HttpClient per se, but with the default constructor for HttpClient, because it creates a new concrete instance of HttpMessageHandler, which is the one that has sockets exhaustion and DNS changes issues mentioned above.
You can see from the source code of IHttpClientFactory that it does not use the parameterless constructor of HttpClient in CreateClient(). Instead, it gets the HttpMessageHandler from a pool and inject it into the created HttpClient.
Whether you are using typed or named clients, you should use the HttpClient instance as if it's a transient object: it is cheap to create and you don't need to cache it for long periods of time.
I'm using the .net core 2.1 HttpFactory and I set a BaseAddress in the startup when calling services.AddHttpClient.
Almost all my calls use the BaseAddress, but some need to call other URLs, so for those, I directly pass the full URL.
Does this dispose of my httpClient and create a new one? Should I instead have 2 different client types and register both with their respective BaseAddress in the startup (can I even do that with the HttpFactory?)?
I'm asking the question, as my integration tests have problems with calls using a "timeout style" cancellation token.
PS: Not using the BaseAddress would be a pain, as the URLs depend on the environment.
Update: I tested registering named clients instead. One for the main cases and another one with a different BaseAddress. It seems to have helped my integration tests, as now they rarely timeout (and when they do, I think it may be related to another issue).
This adds to my original question, as it seems to affect the performance. So again, could it be possible that using the same Client for calls using either the BaseAddress or a full address would prompt disposals/recreations of the Client from the HttpFactory?
I'm writing a RESTful WebServiceA. In order to handle client's request it should call WebServiceB or WebServiceC or WebServiceD. I'm thinking about using HttpClient in WebServiceA to call other services using PostAsync() method.
There are quite a lot articles saying that HttpClient should be re-used as much as possible during the application's lifetime, but these articles seem to be about desktop applications.
Suppose Client1 would call WebServiceA and his call was forwarded to WebServiceB, same time Client2 calls and his call was forwarded to WebServiceC using the same static HttpClient object. Would this object deal with requests correctly in parallel and would a this object's methods be thread-safe in given context?
For test purposes I've made a static HttpClient object in WebServiceA and called WebServiceA's methods from console app in parallel. So far seems to be working OK. However I'm still not sure whether to use a static HttpClient or create and dispose good old HttpWebRequest/Response objects per call. Your suggestions would be highly appreciated.
I have created REST resource using Web API running as a self-hosted process. For performance reasons I would like to be able to call it using persistent HTTP connections. I using OWIN self-hosting.
I really like the asnyc methods for GET, POST, PUT, DELETE in System.Net.Http.HttpClient. They are easy to call and deal with--they return a System.Threading.Tasks.Task which is convenient for what I'm trying to do. I prefer using HttpClient to System.Net.HttpWebRequest.
I'm probably missing something, but it isn't readily apparent to me how to create persistent connections with HttpClient. I'm digging through the System.Net.Http.HttpClientHandler and System.Net.Http.WebRequestHandler classes, but so far I haven't found an option for persistent connections. Google finds all sorts of examples of creating persistent connections using HttpWebRequest. It has a KeepAlive property that can be set to true. Is there a way to set this with HttpClient?
MSDN documentation for HttpClient:
By default, HttpWebRequest will be used to send requests to the server. This behavior can be modified by specifying a different channel in one of the constructor overloads taking a HttpMessageHandler instance as parameter. If features like authentication or caching are required, WebRequestHandler can be used to configure settings and the instance can be passed to the constructor. The returned handler can be passed to one of the constructor overloads taking a HttpMessageHandler parameter.
Is there a way to set the KeepAlive feature on the underlying HttpWebRequest?
The MSDN documentation also says:
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.
Am I to understand from this that the connection pool will optimize for me using persistent connections when a performance benefit can be gained? What if I want there to only ever be a single connection from my client?
You will need to set the MaxIdle time on the ServicePoint for the client. The easiest way is to set the timeout for all service points:
ServicePointManager.MaxServicePointIdleTime = Timeout.Infinite;
You can also set it on the connection to the specific endpoint
var sp = ServicePointManager.FindServicePoint(targetUri);
sp.MasIdleTime = Timeout.Infinite;
I'm not sure what exactly you are trying to solve but have you looked at SignalR ? They have pretty fancy websocket api's that might do the job you are looking for.
If you are not using .NET 4.5 then they do have alternate mechanisms. One I'v seen being used is something like a server/event-stream.