What should be the HttpClient lifetime of a WebAPI client?
Is it better to have one instance of the HttpClient for multiple calls?

创建和处理每个请求HttpClient的开销是多少,如下面的示例(取自http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client):

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:9000/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // New code:
    HttpResponseMessage response = await client.GetAsync("api/products/1");
    if (response.IsSuccessStatusCode)
    {
        Product product = await response.Content.ReadAsAsync<Product>();
        Console.WriteLine("{0}\t${1}\t{2}", product.Name, product.Price, product.Category);
    }
}

推荐答案

HttpClient等于designed to be re-used for multiple calls.即使跨多个线程也是如此. HttpClientHandler具有旨在跨呼叫重复使用的凭证和Cookie.拥有一个新的HttpClient实例需要重新设置所有这些东西. 此外,DefaultRequestHeaders属性还包含用于多个调用的属性.必须在每个请求上重置这些值,这一点就落空了.

HttpClient的另一个主要优点是能够将HttpMessageHandlers添加到请求/响应管道中,以应用横切关注点.这些可以用于日志(log)记录、审核、节流、重定向处理、脱机处理、捕获度量.各种各样的事情.如果在每个请求上创建了一个新的HttpClient,那么需要在每个请求上设置所有这些消息处理程序,并且还需要提供这些处理程序的请求之间共享的任何应用程序级状态.

您使用HttpClient的功能越多,就越能看到重用现有实例是有意义的.

然而,在我看来,最大的问题是,当处置HttpClient个类时,它会处置HttpClientHandler,然后强制关闭由ServicePointManager管理的连接池中的TCP/IP连接.这意味着具有新的HttpClient的每个请求需要重新建立新的TCP/IP连接.

从我的测试来看,在局域网上使用纯HTTP对性能的影响微乎其微.我怀疑这是因为有一个底层TCP Keep Alive使连接保持打开状态,即使在HttpClientHandler次try 关闭它时也是如此.

在互联网上的请求中,我看到了一个不同的故事.由于每次都必须重新打开请求,我已经看到40%的性能下降.

我怀疑HTTPS连接的命中率会更高.

我的建议是,对于您连接的每个不同的API,设置为keep an instance of HttpClient for the lifetime of your application.

Asp.net相关问答推荐

Razor 页面客户端站点验证不起作用

如何在asp.net中单击按钮的新选项卡中打开页面?

*不*使用 asp.net 会员提供程序是个坏主意吗?

AppendHeader 是否与 AddHeader 完全相同?

在 C# 中以编程方式添加元标记

如何缓存数据库表以防止在 Asp.net C# mvc 中出现许多数据库查询

如何在 ASP.NET Web 窗体中使用依赖注入

通过 jQuery 调用 ASP.NET 服务器端方法

显示单选按钮列表内联

如何在同一解决方案中从 MVC 项目调试 Web API 项目

ASP.NET 中的 <% %>(嵌入式代码块)

每个 'HttpRequest' 在 ASP.NET 中都有自己的线程吗?

会话变量保存在哪里?

什么是实体框架中的复杂类型以及何时使用它?

如何在 ASP.Net 网络表单中使用标签?

禁用 web.config 继承?

Azure Functions 中的 DI

如何将表从存储过程检索到数据表?

如何在 ASP.NET 中通过 LAN 访问您的网站

.Net 上是否有 URL 验证器?