I'm using RestSharp to make API calls. What I have learnt for HttpClient is that it can lead to socket exhaustion when too many instances are created: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
The RestClient class also accepts an HttpClient parameter, so I guess it's using HttpClient internally.
I'm not sure how RestSharp handles HttpClient instances internally, but should I instantiate the RestClient with a HttpClient created by the IHttpClientFactory implementation?
new RestClient(httpClientFactory.CreateClient())
When you pass the HttpClient instance like that, it won't be disposed. The intention is that you might have a pre-configured HttpClient instance used as a singleton. It's not a good idea to dispose an external dependency by default, so RestSharp doesn't do it.
Besides, the issue with socket exhaustion is not caused by HttpClient being instantiated for each request but by the underlying HttpMessageHandler.
If you want to use the IHttpClientFactory internal instance caching (it doesn't cache the client, it caches the HttpMessageHandler instances), you can do it like this:
using var httpClient = httpClientFactory.CreateClient();
using var restClient = new RestClient(httpClient);
You can also tell RestSharp to dispose the HttpClient instance:
using var restClient = new RestClient(httpClientFactory.CreateClient(), true);
and the factory will take care of caching the message handler.
The next major version of RestSharp will hopefully make it a bit easier.
Related
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 am trying to understand how HttpClient has been implemented for Captcha in Nop Commerce and for the sake of testability how creating new instance of HttpClient has been manage in Nop Commerce project.
I came across ValidateCaptchaAttribute and ValidateCaptchaFilter and I see HttpClient has been wrapped inside CaptchaHttpClient class
but I don't understand from where does CaptchaHttpClient receive dependency for HttpClient and from where constructor of CaptchaHttpClient class is being called.
Inside ServiceCollectionExtensions class I see below code:
public static void AddNopHttpClients(this IServiceCollection services)
{
//default client
services.AddHttpClient(NopHttpDefaults.DefaultHttpClient).WithProxy();
//client to request current store
services.AddHttpClient<StoreHttpClient>();
//client to request nopCommerce official site
services.AddHttpClient<NopHttpClient>().WithProxy();
//client to request reCAPTCHA service
services.AddHttpClient<CaptchaHttpClient>().WithProxy();
}
But I don't see where HttpClient object is created:
var client = new HttpClient() // Where this is done?
Am I perhaps missing something?
Nop Commerce Version = 4.20
From the documentation:
Adds the IHttpClientFactory and related services to the IServiceCollection and configures a binding between the TClient type and a named HttpClient. The client name will be set to the type name of TClient.
Roughly translated, services.AddHttpClient<CaptchaHttpClient>() means that CaptchaHttpClient has a dependency on HttpClient. This says that when injecting HttpClient into CaptchaHttpClient, don't just create a new one - use an implementation of IHttpClientFactory to provide one and inject the HttpClient it creates.
This means that you're not managing the lifetime of the HttpClient. The ServiceProvider is doing that behind the scenes. (You're not responsible for creating the client factory either.)
This documentation explains why this exists and how it works.
A Typed Client is, effectively, a transient object, meaning that a new instance is created each time one is needed and it will receive a new HttpClient instance each time it's constructed. However, the HttpMessageHandler objects in the pool are the objects that are reused by multiple Http requests.
This means:
The thing you're registering - in this case CaptchaHttpClient is transient so that each time it's resolved, a new instance is created.
Each time it is created, a new HttpClient is created and injected.
Although the HttpClient is new, the HttpMessageHandler it depends upon is reused.
This uses a pool of HttpMessageHandler instances that we don't have to manage. Our class just depends on HttpClient without having to worry about the negative side effects that happen when we create/dispose an HttpClient each time we need one.
I found this article helpful in furthering my understanding of IHttpClientFactory patterns.
When defining typed clients in your ConfigureServices method, the
typed service is registered with transient scope. This means that a
new instance is created by the DI container every time one is needed.
The reason this occurs is that a [sic] HttpClient instance is injected into
the typed client instance. That HttpClient instance is intended to
be short lived so that the HttpClientFactory can ensure that the
underlying handlers (and connections) are released and recycled.
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.
In the unit Test cases, TestServer is used for in-memory hosting of the WebAPI. After this, we are trying to make HttpConnection to this hosted WebAPI using some code like this:
HttpClient client= new HttpClient();
client.BaseAddress("url");
client.GetAsync("url").Result();
This code gives an exception, with the error message
"Connection refused".
But if we get the HttpClient object using the below code and follow the above steps, it works fine.
TestServer.CreateClient()
What could be the reason behind it? Is it because it's an in-memory hosted WebAPI? No actual Http context is there??
That's by design. When you call TestServer.CreateClient() a client with special HttpMessageHandler is created. That handler allows to directly call APIs under test without exposing it as HTTP server:
public class TestServer : IServer, IDisposable
{
public HttpClient CreateClient()
{
HttpClient httpClient = new HttpClient(this.CreateHandler());
...
}
}
That should be faster and suitable enough for unit-testing. For integration testing, run a Kestrel server at test startup.
P.S. I hope your application design became better with DI instead of explicit building. That's nice you resolved the problem this way.
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.