2

In a web-request I want to do a call to another server using Microsoft HttpClient. I am using MVC4 (hosted in IIS), and castle-windsor as IOC-container. I read that the HttpClient is designed to live during serveral calls, and my question is how I should implement this.

I come up with a few options:

  1. Ignore the fact that HttpClient is designed for multiple calls, and create a new one each time i need one.
  2. Create a Singleton(lifestyle in castle) object which stores the HttpClient between calls. Are there any risks with this? Will the performace be bad, if multiple web-request is using the same HTTP-client?

Are there any better pattern to do this?

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
jabocop
  • 133
  • 1
  • 2
  • 8

2 Answers2

2

I would use LifestyleTransient to create a new one for each request. That's safest when you're not sure that the class can function as a singleton.

It's also not a bad idea to depend on an abstraction (an interface) rather than on the HttpClient directly unless you're certain that the class would never be used apart from making HTTP requests. Even then it may make unit testing easier. That's one of the big benefits of using Windsor or another DI container. Otherwise there's not much benefit over just instantiating an HttpClient directly in your class.


Update. I did some looking and found this answer indicating that an HttpClient should be reused for a given API. It's highly upvoted and I don't see any dissent from experience (or otherwise) so I'm going to reference it when doing some near-term development.

I would implement this by defining a strongly-typed client class that implements an interface, and then depending on the interface in my classes (not directly on the client.) Then Windsor can create the class for an interface and maintain it as a singleton.

Community
  • 1
  • 1
Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • Does that means that the `HttpClient` can handle multiple calls (from different threads) at once with good performace? If the calls are made in a lock the performace would be bad and it could in that case be a good idea to implement a pool of `HttpClient` – jabocop Apr 25 '16 at 15:16
  • That's what the discussion indicates. In fact, it suggests that not doing that could result in performance issues. I don't have any experience with high volume yet, which is why I suggested erring on the side of caution, but I've got some work of that nature coming up, so I'm going to keep looking for something definitive. But the answer, upvotes, and comments make a good case for it. – Scott Hannen Apr 25 '16 at 16:46
  • Thanks alot for your comments. I will implement the HttpClient as a singleton. I also found the [documentation](https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.110%29.aspx) for HttpClient from Microsoft (updated for .Net Framwork 4.5 and 4.6) which indicates that a bunch of methods actually are thread safe. – jabocop Apr 25 '16 at 18:26
0

By default if you create a new instance of HttpClient for each call, then each call will create a new TCP connection, and this will cause latency and reduced throughput. If you want to have a new HttpClient instance because it's got per-call data on it, then you can have a singleton HttpClientHandler, pass it to the HttpClient ctor, and that will share the TCP connections across the HttpClient instances.

Scott, here are three approaches we have used that work. I hope this helps, I'm new to stackoverflow so can't post more than two links apparently.

1) Just have a static/singleton HttpClient, and pass any per-call headers with HttpRequestMessage as described here

2) Have a static/singleton WebRequest|HttpClientHandler, and pass that to the HttpClient ctor with disposeHandler set to false.

3) In some cases, we had a DelegatingHandler instrumentation library that needed to be disposed after each HttpClient call. So we created a WebRequestHandler that does nothing in Dispose() as below, passed that to the DelegatingHandler ctor, and then passed the DelegatingHandler to the HttpClient ctor with disposeHandler set to false.

public class LongLivedWebRequestHandler : WebRequestHandler
{
    public override void Dispose()
    {
        // Do nothing...
    }
}
Community
  • 1
  • 1
  • Can you refer me to any documentation or examples? This sounds like something I need to know about. Thanks – Scott Hannen Apr 25 '16 at 12:00
  • Yeah, the documentation was a little thin. We found it making calls from one Azure classic web service to another and the difference between our outbound and inbound latency was ~100ms I think. Sharing a long-lived WebRequest|HttpClientHandler, the per-hop penalty dropped to ~20ms. There are three examples that work. – AlejandroOeste Apr 28 '16 at 14:40