什么是在客户端的WebAPI创建每次调用一个新的HttpClient的开销? [英] What is the overhead of creating a new HttpClient per call in a WebAPI client?

查看:130
本文介绍了什么是在客户端的WebAPI创建每次调用一个新的HttpClient的开销?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应该是什么的WebAPI客户端中的HttpClient寿命是多少?它是更好地在客户端的一个实例多个电话?

什么是创造和下面的例子在释放一个HttpClient的每个请求,喜欢的开销(从<一所href=\"http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client\">http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client):

 使用(VAR的客户=新的HttpClient())
{
    client.BaseAddress =新的URI(HTTP://本地主机:9000 /);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(新MediaTypeWithQualityHeaderValue(应用/ JSON));    //新的code:
    HTT presponseMessage响应=等待client.GetAsync(API /产品/ 1);
    如果(response.IsSuccessStatus code)
    {
        产品产品=等待response.Content.ReadAsAsync&GT;产品及GT;();
        Console.WriteLine({0} \\ T $ {1} \\ t {2},product.Name,product.Price,product.Category);
    }
}


解决方案

的HttpClient 设计成可重复使用多次调用。甚至可以跨多个线程。
HttpClientHandler 有凭据和旨在通过调用被重新使用的饼干。有一个新的的HttpClient 实例都需要重新设定所有的这些东西。
此外, DefaultRequestHeaders 属性包含用于多次调用属性。不必对每个请求重置这些价值观战胜的地步。

的HttpClient 的另一个主要好处是增加 HttpMessageHandlers 进入请求/响应管道申请跨部门的能力顾虑。这些可能是日志,审计,节流,重定向处理,离线处理,捕捉指标。各种不同的东西。如果对每个请求创建一个新的HttpClient,那么所有的这些消息处理程序必须对每个请求,并在某种程度上是为这些处理请求之间共享还需要提供应用层的状态设置。

越多,您使用的HttpClient的特点,你越会发现重用现有的实例是有道理的。

不过,最大的问题,我的看法是,当一个了HTTPClient 类配置,其配置 HttpClientHandler ,然后强行关闭在连接池是由 ServicePointManager 管理​​TCP / IP 连接。这意味着,每个请求一个新的的HttpClient 需要重新建立一个新的 TCP / IP 连接。

这是我的测试,使用普通的HTTP在LAN上,则PERF命中还算可以忽略不计。我怀疑这是因为持有该连接打开,即使 HttpClientHandler 试图关闭它的底层TCP存活。

在那走在互联网上的请求,我看到一个不同的故事。我见过一个40%PERF由于命中不必每次都重新打开请求。

我怀疑在 HTTPS 连接命中会更糟。

我的建议是为保持HttpClient的实例为您的应用作为您连接到每个不同API的寿命。

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

What's the overhead of creating and disposing a HttpClient per request, like in example below(taken from 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 has been designed to be re-used for multiple calls. Even across multiple threads. The HttpClientHandler has Credentials and Cookies that are intended to be re-used across calls. Having a new HttpClient instance requires re-setting up all of that stuff. Also, the DefaultRequestHeaders property contains properties that are intended for multiple calls. Having to reset those values on each request defeats the point.

Another major benefit of HttpClient is the ability to add HttpMessageHandlers into the request/response pipeline to apply cross cutting concerns. These could be for logging, auditing, throttling, redirect handling, offline handling, capturing metrics. All sorts of different things. If a new HttpClient is created on each request, then all of these message handlers need to be setup on each request and somehow any application level state that is shared between requests for these handlers also needs to be provided.

The more you use the features of HttpClient, the more you will see that reusing an existing instance makes sense.

However, the biggest issue, in my opinion is that when a HTTPClient class is disposed, it disposes HttpClientHandler, which then forcibly closes the TCP/IP connection in the pool of connections that is managed by ServicePointManager. This means that each request with a new HttpClient requires re-establishing a new TCP/IP connection.

From my tests, using plain HTTP on a LAN, the perf hit is fairly negligible. I suspect this is because there is an underlying TCP keepalive that is holding the connection open even when HttpClientHandler tries to close it.

On requests that go over the internet, I have seen a different story. I have seen a 40% perf hit due to having to re-open the request every time.

I suspect the hit on a HTTPS connection would be even worse.

My advice is to keep an instance of HttpClient for the lifetime of your application for each distinct API that you connect to.

这篇关于什么是在客户端的WebAPI创建每次调用一个新的HttpClient的开销?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆