Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用WebApi中的静态或单个HttpClient实例,连接池中有许多处于时间等待状态的连接_C#_Asp.net Core_.net Core_Httpclient_Connection Pooling - Fatal编程技术网

C# 使用WebApi中的静态或单个HttpClient实例,连接池中有许多处于时间等待状态的连接

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,但它没有用,因为我在注入的服务上遇到了同样的问题 这

在使用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();
}
}
}
}
到达当前代码之前的调用堆栈如下所示:

  • 启动时,WebApi应用程序调用
    CustomHttpClientManager
    Initialize
    方法,该方法仅实例化一次
    HttpClient
  • 客户端调用WebApi控制器的操作
  • 该操作调用业务逻辑类(服务类)
  • 逻辑类使用
    CustomHttpClientManager
    GetAsString
    方法,通过使用先前实例化的
    HttpClient
  • 客户端执行大量对WebApi的调用(大约每分钟200个rq),当在命令提示符下运行
    netstat-ano
    时,它会显示一个相当长的池连接列表,其状态为TIME\u WAIT,这表明
    HttpClient
    根本没有重用池中的连接。这些连接仅在使用后2分钟左右出现

    除此之外,我的其他方法是

    • 使用
      .AddHttpClient()
    • 使用上面相同的类,但使用线程安全的单例版本
    他们都没有工作。我不知道还能做什么。这已经让我连续两天发疯了

    我已经从一个简单的控制台应用程序测试了这个实现,但问题没有发生。这意味着WebApi操作会在响应调用方后继续关闭外部连接,一旦发出另一个调用,它会在池中创建另一个连接,并继续进行下一个输入请求

    顺便说一句,我使用的是.NETCore3.1

    提前感谢

    使用

    PooledConnectionLifetime=TimeSpan.FromSeconds(30)

    表示连接在30秒后从池中删除

    您可以将其更改为更长的时间(例如10分钟)-机器人不会太长而无法适应
    DNS会发生变化。

    使用
    IHttpClientFactory
    是一种方法,应该可以做到这一点。当你尝试时,不知道出了什么问题。但这肯定是我发现最常用的推荐方法。@Fildor我还发现
    IHttpClientFactory
    是最推荐的方法,尽管如此,我已经尝试注入到我正在使用的服务类中的任何一个,当它不起作用时,我尝试通过操作控制器注入它(如果在使用
    .AddHttpClient()
    时未指定任何服务类,则可以执行此操作)我正在调用,但此方法也具有相同的行为