C# 使用WebApi中的静态或单个HttpClient实例,连接池中有许多处于时间等待状态的连接
在使用HttpClient时,我已经绞尽脑汁试图阻止池中的多个连接 我已经构建了一个RESTWebAPI,通过在其中使用HttpClient调用外部端点。为了执行上述外部调用,客户机多次调用控制器的操作 以前我使用的是WebClient,但当发出几个请求时,它遭受了socketexhoustion的痛苦。在网上搜索时,我发现迁移到HttpWebClient可以解决静态使用或在单例中使用的问题。我甚至尝试实现IHttpClientFactory,但它没有用,因为我在注入的服务上遇到了同样的问题 这是我当前的实现,经过几次重构。抱歉,如果目前这段代码不是最佳的,但在多次重写之后,这是我最后的选择C# 使用WebApi中的静态或单个HttpClient实例,连接池中有许多处于时间等待状态的连接,c#,asp.net-core,.net-core,httpclient,connection-pooling,C#,Asp.net Core,.net Core,Httpclient,Connection Pooling,在使用HttpClient时,我已经绞尽脑汁试图阻止池中的多个连接 我已经构建了一个RESTWebAPI,通过在其中使用HttpClient调用外部端点。为了执行上述外部调用,客户机多次调用控制器的操作 以前我使用的是WebClient,但当发出几个请求时,它遭受了socketexhoustion的痛苦。在网上搜索时,我发现迁移到HttpWebClient可以解决静态使用或在单例中使用的问题。我甚至尝试实现IHttpClientFactory,但它没有用,因为我在注入的服务上遇到了同样的问题 这
公共静态类CustomHttpClientManager
{
私有静态httpclientu HttpClient;
公共静态void Initialize()
{
ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback+=
(发件人、证书、链、sslPolicyErrors)=>真;
CookieContainer cookies=新CookieContainer();
_httpClient=新的httpClient(
新SocketsHttpHandler()
{
Proxy=新的CustomProxy(),
UseProxy=true,
PooledConnectionLifetime=TimeSpan.FromSeconds(30),
PooledConnectionIdleTimeout=TimeSpan.FromSeconds(20),
MaxConnectionsPerServer=2,
CookieContainer=饼干,
AutomaticDecompression=DecompressionMethods.GZip | DecompressionMethods.Deflate
});
_httpClient.DefaultRequestHeaders.ConnectionClose=false;
}
公共静态异步任务GetAsString(字符串url){
HttpResponseMessage响应=null;
试一试{
HttpRequestMessage HttpRequestMessage=新建HttpRequestMessage()
{
RequestUri=新的Uri(url),
Method=HttpMethod.Get
};
添加(“接受”,“text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”);
添加(“接受编码”、“gzip、deflate、sdch”);
添加(“接受语言”,“en GB,en US;q=0.8,en;q=0.6”);
添加(“接受字符集”,“ISO-8859-1,utf-8;q=0.7,*;q=0.3”);
response=await\u httpClient.sendsync(httpRequestMessage);
if(响应。IsSuccessStatusCode){
return wait response.Content.ReadAsStringAsync();
}
否则{
抛出新异常(例如消息);
}
}
捕获(例外情况除外){
return$“无法从:{connectionParameters.Url}获取响应,原因是:{ex.Message}”;
}
最后{
if(响应!=null){
response.Dispose();
}
}
}
}
到达当前代码之前的调用堆栈如下所示:
CustomHttpClientManager
的Initialize
方法,该方法仅实例化一次HttpClient
CustomHttpClientManager
的GetAsString
方法,通过使用先前实例化的HttpClient
netstat-ano
时,它会显示一个相当长的池连接列表,其状态为TIME\u WAIT,这表明HttpClient
根本没有重用池中的连接。这些连接仅在使用后2分钟左右出现
除此之外,我的其他方法是
- 使用
.AddHttpClient()
- 使用上面相同的类,但使用线程安全的单例版本
DNS会发生变化。使用
IHttpClientFactory
是一种方法,应该可以做到这一点。当你尝试时,不知道出了什么问题。但这肯定是我发现最常用的推荐方法。@Fildor我还发现IHttpClientFactory
是最推荐的方法,尽管如此,我已经尝试注入到我正在使用的服务类中的任何一个,当它不起作用时,我尝试通过操作控制器注入它(如果在使用.AddHttpClient()
时未指定任何服务类,则可以执行此操作)我正在调用,但此方法也具有相同的行为