繁体   English   中英

静态HttpClient仍然创建TIME_WAIT tcp端口

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM