在多线程中使用HttpClient时的套接字耗尽


拥有一个HttpClient实例并适当配置MaxConnectionsPerServer

有一篇使用私有静态HttpClient _httpClient = new HttpClient()的文章;而不是像使用(var httpClient = new HttpClient())那样丢弃实例,以便不使用HttpClient耗尽套接字。但是,尽管这对于单线程处理非常有效,但会在多线程,高负载环境中导致套接字耗尽。

有关套接字耗尽的详细信息将在其他文章中进行介绍,因此在此将其省略,但是由于MaxConnectionsPerServer默认为int.MaxValue并且连接数实际上是无限的,所以
有必要如下明确设置连接数。

1
2
3
4
private static HttpClient _httpClient = new HttpClient(new HttpClientHandler
{
    MaxConnectionsPerServer = 4
});

Azure Stotage库中的HttpClient连接数

由于上述原因,即使在BLOB的API处理和Azure存储的队列中也会发生套接字耗尽。
(在使用多个线程处理的环境(例如Azure Functions的队列触发器)中,SocketException在高负载下发生)
由于DelegatingHandler参数已从Azure Stotage库的v9.4.1版本添加到CloudBlobClient和CloudQueueClient构造函数中,因此实现处理程序并按如下所示指定连接数似乎很不错。

(使用.Net Core v3.0,Microsoft.Azure.Storage.Blob(v11.1.3),Microsoft.Azure.Storage.Queue(v11.1.3)检查)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HttpClientInjectionHandler : DelegatingHandler
{
    private bool IsFirstCall = true;
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (IsFirstCall)
        {
            var handler = (HttpClientHandler)InnerHandler;
            handler.MaxConnectionsPerServer = 5;
            IsFirstCall = false;
        }

        return base.SendAsync(request, cancellationToken);
    }
}
1
2
private static CloudStorageAccount _storageAccount = CloudStorageAccount.Parse(@"Connection String...");
private static CloudBlobClient _blobClient = new CloudBlobClient(_storageAccount.BlobEndpoint, _storageAccount.Credentials, new HttpClientInjectionHandler());

Azure存储库版本说明

?v9.3.3:WindowsAzure.Storage

1
2
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

v9.4.0?v11:Microsoft.Azure.Storage.Blob

1
2
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;

v12 azure.Storage.Blobs

类名不同于

v11。 v12在构造函数中没有DelegatingHandler参数。
?v11:CloudBlobClient
v12?:BlobServiceClient

参考文献

  • 您正在使用HTTPCLIENT WRONG,并且正在破坏您的软件
  • 在多个线程中操作HttpClient时的注意事项
  • 谨慎讨论处理.NET(框架)HttpClient