Search code examples
c#asp.net-corehttpclientobject-lifetimehttpclientfactory

Long lived HttpClient created by HttpClientFactory


I've read that HttpMessageHandlers are recycled every 2 minutes, but I'm not sure if a new one is assigned to an existing HttpClient?

I've tested it out by using SetHandlerLifetime(TimeSpan.FromSeconds(5)); and even after 2 minutes with countless requests, the httpClient is continuing to work, which is a good sign?

Does that mean that I have no cause for concern with DNS changes/socket exhaustion?

Inside ConfigureServices method:

var myOptions = app.ApplicationServices.GetService<IOptionsMonitor<MyOptions>>();
HttpClient httpClient = app.ApplicationServices.GetService<IHttpClientFactory>().CreateClient();
MyStaticObject.Configure(myOptions, httpClient);

EDIT: Added some sample code.


Solution

  • There are a few things to look at here, with the first being does MyStaticObject actually need to be static? If it does, I would recommend instead registering it as a Singleton so that you can still leverage dependency injection. Once you have done that, you can register IHttpClientFactory and use it from your code. Your ConfigureServices method may end up looking something like this

    public void ConfigureServices(IServiceCollection services)
    {
      //The base extension method registers IHttpClientFactory
      services.AddHttpClient();
      services.AddSingleton<IMySingletonObject, MySingletonObject>();
    }
    

    Then in your consuming class, MySingletonObject in this case, you would configure it as such

    public class MySingletonObject
    {
      private readonly IHttpClientFactory _clientFactory;
    
      public MySingletonObject(IHttpClientFactory clientFactory)
      {
        _clientFactory = clientFactory;
      }
    
      public async Task SomeMethodThatUsesTheClient()
      {
        var client = _clientFactory.CreateClient();
        //use the client
      }
    }
    

    The reason for this is that IHttpClientFactory handles the lifetime and pool concerns for us. Per the docs:

    Manages the pooling and lifetime of underlying HttpClientMessageHandler instances. Automatic management avoids common DNS (Domain Name System) problems that occur when manually managing HttpClient lifetimes.

    This happens when you make the CreateClient call, so you want to do this inside the code using the client, as opposed to on startup of your application.

    As a side note, if you do not need this class to be a singleton at all, you can use the extenion services.AddHttpClient<IMyClass, MyClass>() and inject an HttpClient directly into the class. The DI container will handle getting a client from the factory behind the scenes for you.