![](/img/trans.png)
[英]Many connections in TIME_WAIT state in connection pool, using either static or single HttpClient instance in WebApi
[英]Static HttpClient still creating TIME_WAIT tcp ports
我正在使用.NET Framework中的HttpClient(4.5.1 +,4.6.1和4.7.2)遇到一些有趣的行为。 我已经提议在工作项目中进行一些更改,以便在每次使用时不处理HttpClient,因为TCP端口使用率很高的已知问题,请参阅https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong / 。
我已经调查了这些更改,以检查事情是否按预期工作,并发现我们仍然遇到与以前相同的TIME_WAIT端口。
为了确认我提议的更改是正确的,我已经向应用程序添加了一些额外的跟踪,以确认我在整个应用程序中使用了相同的HttpClient实例。 我已经使用过简单的测试应用程序(取自上面链接的aspnetmonsters网站。
using System;
using System.Net.Http;
namespace ConsoleApplication
{
public class Program
{
private static HttpClientHandler { UseDefaultCredentials = true };
private static HttpClient Client = new HttpClient(handler);
public static async Task Main(string[] args)
{
Console.WriteLine("Starting connections");
for(int i = 0; i<10; i++)
{
var result = await Client.GetAsync("http://localhost:51000");
Console.WriteLine(result.StatusCode);
}
Console.WriteLine("Connections done");
Console.ReadLine();
}
}
}
仅当使用Windows身份验证连接到IIS中承载的站点时,才会出现此问题。 通过将身份验证设置为匿名(问题消失)并返回到Windows身份验证(问题重新出现),我可以轻松地重现问题。
Windows身份验证的问题似乎不仅限于提供程序的范围。 如果您使用Negotiate或NTLM,它也会遇到同样的问题。 如果机器只是工作站或域的一部分,也会出现问题。
出于兴趣,我创建了一个dotnet核心2.1.0控制台应用程序,该问题根本不存在,并按预期工作。
TLDR:有没有人知道如何解决这个问题,或者它可能是一个错误?
精简版
如果要使用NTLM身份验证重用连接,请使用.NET Core 2.1
长版
当使用NTLM身份验证时,我很惊讶地发现“旧的”HttpClient确实为每个请求使用了不同的连接。 这不是一个错误 - 在.NET Core 2.1 HttpClient使用HttpWebRequest之前,它会在每次NTLM身份验证调用后关闭连接。
HttpWebRequest.UnsafeAuthenticatedConnectionSharing属性的文档中对此进行了描述,该属性可用于启用共享连接:
此属性的默认值为false,这会导致在请求完成后关闭当前连接。 每次发出新请求时,您的应用程序都必须经过身份验证序列。
如果此属性设置为true,则在执行身份验证后,用于检索响应的连接将保持打开状态。 在这种情况下,将此属性设置为true的其他请求可以使用该连接而无需重新进行身份验证。
风险在于:
如果已经为用户A验证了连接,则用户B可以重用A的连接; 基于用户A的凭证完成用户B的请求。
如果理解风险,并且应用程序不使用模拟,可以使用WebRequestHandler配置HttpClient并设置UnsafeAuthenticatedConnectionSharing ,例如:
HttpClient _client;
public void InitTheClient()
{
var handler=new WebRequestHandler
{
UseDefaultCredentials=true,
UnsafeAuthenticatedConnectionSharing =true
};
_client=new HttpClient(handler);
}
WebRequestHandler 不公开允许通过ID对连接进行分组的HttpWebRequest.ConnectionGroupName ,因此无法处理模拟。
.NET Core 2.1
HttpClient在.NET Core 2.1中重写,并使用套接字,最小分配,连接池等实现所有HTTP,网络功能。它还单独处理NTLM质询/响应流,因此可以使用相同的套接字连接来提供不同的经过身份验证的请求。
如果有人有兴趣,你可以追逐从HttpClient到SocketsHttpHanlder到HttpConnectionPoolManager,HttpConnectionPool,HttpConnection,AuthenticationHelper.NtAuth的调用,然后回到HttpConnection发送原始字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.