使用城堡温莎的 MVC4 中 HttpClient 的生活方式

Lifestyle of a HttpClient in MVC4 using castle-windsor

在网络请求中,我想使用 Microsoft HttpClient 调用另一台服务器。我正在使用 MVC4(托管在 IIS 中)和 castle-windsor 作为 IOC 容器。我读到 HttpClient 设计为在多次调用期间运行,我的问题是我应该如何实现它。

我想出了几个选项:

  1. 忽略 HttpClient 是为多次调用而设计的这一事实,每次需要时都创建一个新的。
  2. 创建一个 Singleton(lifestyle in castle) 对象,它在调用之间存储 HttpClient。这有什么风险吗?如果多个网络请求使用相同的 HTTP 客户端,性能会很差吗?

有没有更好的模式来做到这一点?

我会使用 LifestyleTransient 为每个请求创建一个新的。当您不确定 class 是否可以作为单例运行时,这是最安全的。

依赖抽象(接口)而不是直接依赖 HttpClient 也是一个不错的主意,除非您确定 class 除了发出 HTTP 请求外永远不会被使用。即使那样,它也可能使单元测试更容易。这是使用 Windsor 或其他 DI 容器的一大好处。否则,直接在 class 中实例化一个 HttpClient 并没有多大好处。


更新。我做了一些查找,发现 this answer 表明应该为给定的 API 重用 HttpClient。它受到高度赞扬,我没有看到任何来自经验(或其他)的异议,所以我将在进行一些近期开发时参考它。

我会通过定义一个实现接口的强类型客户端 class 来实现这一点,然后根据我的 classes 中的接口(不直接在客户端上。)然后是温莎可以为接口创建 class 并将其维护为单例。

默认情况下,如果您为每次调用创建一个新的 HttpClient 实例,则每次调用都会创建一个新的 TCP 连接,这将导致延迟和吞吐量降低。如果你想要一个新的 HttpClient 实例,因为它上面有 per-call 数据,那么你可以有一个单例 HttpClientHandler,将它传递给 HttpClient ctor,这将在 HttpClient 实例之间共享 TCP 连接。

斯科特,这是我们在这项工作中使用的三种方法。我希望这会有所帮助,我是 Whosebug 的新手,所以显然 post 不能超过两个链接。

1) 只需要一个 static/singleton HttpClient,并按照 here

所述将任何 per-call headers 与 HttpRequestMessage 传递

2) 有一个 static/singleton WebRequest|HttpClientHandler,并将其传递给 HttpClient ctor,并将 disposeHandler 设置为 false。

3) 在某些情况下,我们有一个 DelegatingHandler 检测库,需要在每次 HttpClient 调用后进行处理。因此,我们创建了一个在 Dispose() 中不执行任何操作的 WebRequestHandler,如下所示,将其传递给 DelegatingHandler ctor,然后将 DelegatingHandler 传递给 HttpClient ctor,并将 disposeHandler 设置为 false。

public class LongLivedWebRequestHandler : WebRequestHandler
{
    public override void Dispose()
    {
        // Do nothing...
    }
}