客户端中为每次调用创建一个新的

客户端中为每次调用创建一个新的

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

问题描述

WebAPI 客户端的 HttpClient 生命周期应该是多少?
为多个调用使用一个 HttpClient 实例是否更好?

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/调用-a-web-api-from-a-net-client):

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}	${1}	{2}", product.Name, product.Price, product.Category);
    }
}

推荐答案

HttpClient设计为可重复用于多次调用.甚至跨多个线程.HttpClientHandler 具有旨在跨调用重复使用的凭据和 Cookie.拥有一个新的 HttpClient 实例需要重新设置所有这些东西.此外,DefaultRequestHeaders 属性包含用于多次调用的属性.必须在每个请求上重置这些值会失去意义.

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.

HttpClient 的另一个主要好处是能够将 HttpMessageHandlers 添加到请求/响应管道中以应用横切关注点.这些可能用于日志记录、审计、限制、重定向处理、离线处理、捕获指标.各种不同的东西.如果在每个请求上创建一个新的 HttpClient,那么所有这些消息处理程序都需要在每个请求上设置,并且以某种方式在这些处理程序的请求之间共享的任何应用程序级别状态也需要提供.

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.

您使用 HttpClient 的功能越多,您就越会发现重用现有实例更有意义.

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

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

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.

根据我的测试,在 LAN 上使用纯 HTTP,性能影响可以忽略不计.我怀疑这是因为即使 HttpClientHandler 试图关闭它,也有一个底层 TCP keepalive 保持连接打开.

From my tests, using plain HTTP on a LAN, the performance 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.

对于通过互联网发送的请求,我看到了一个不同的故事.由于每次都必须重新打开请求,我看到了 40% 的性能下降.

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

我怀疑对 HTTPS 连接的攻击会更糟.

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

我的建议是在应用程序的整个生命周期内为每个不同的 API 保留一个 HttpClient 实例.

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

08-04 06:43